我有一个正在更新以使用PHP7的AngularJS应用程序。目前,我为会话设置了一个自定义会话处理程序:
自定义会话处理程序(session.php)
function sess_open( $path, $name ) {
return true;
}
function sess_close( ) {
$sessionId = session_id();
return true;
}
function sess_read( $id ) {
$db = dbConn::getConnection();
$stmt = "SELECT session_data FROM session where session_id =" . $db->quote($id);
$result = $db->query($stmt);
$data = $result->fetchColumn();
$result->closeCursor();
return $data;
}
function sess_write( $id, $data ) {
$db = dbConn::getConnection();
$tstData = sess_read( $id );
if (!is_null($tstData)) {
// if it does then do an update
$stmt = "UPDATE session SET session_data =" . $db->quote($data) . " WHERE session_id=" . $db->quote($id);
$db->query($stmt);
}
else {
// else do an insert
$stmt = "INSERT INTO session (session_id, session_data) SELECT ". $db->quote($id) . ", ". $db->quote($data) . " WHERE NOT EXISTS (SELECT 1 FROM session WHERE session_id=" . $db->quote($id) . ")";
$db->query($stmt);
}
return true;
}
function sess_destroy( $id ) {
$db = dbConn::getConnection();
$stmt = "DELETE FROM session WHERE session_id =" . $db->quote($id);
setcookie(session_name(), "", time() - 3600);
return $db->query($stmt);
}
function sess_gc( $lifetime ) {
$db = dbConn::getConnection();
$stmt = "DELETE FROM session WHERE timestamp < NOW() - INTERVAL '" . $lifetime . " second'";
return $db->query($stmt);
}
session_name('PROJECT_CUPSAW_WEB_APP');
session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
session_start();
ob_flush();在我的app.js中,我有一个连续的检查,以查看用户是否经过身份验证并能够访问应用程序。
App.js
/*
* Continuous check for authenticated permission to access application and route
*/
app.run(function($rootScope, $state, authenticationService, ngToast) {
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {
authenticationService.isAuthenticated()
.success(function () {
if(toState.permissions) {
ngToast.dismiss();
event.preventDefault();
$state.go("logout"); // NEEDS TO CHANGE - Unauthorized access view
return;
}
})
.error(function () {
ngToast.dismiss();
event.preventDefault();
localStorage.clear();
$state.go("authentication"); // User is not authenticated; return to login view
return;
});
ngToast.dismiss();
});
});在上面的代码中,isAuthenticated运行isUserAuthorized.php
isAuthenticated
/*
* Check if user is authenticated; set role/permissions
*/
this.isAuthenticated = function() {
return $http.post(baseUrl + '/isUserAuthorized.php');
};isUserAuthorized.php
<?php
require_once 'session.php';
// Check to ensure user is authenticated to initiate request
if (array_key_exists('authenticated', $_SESSION) && $_SESSION['authenticated']) {
return http_response_code(200);
} else {
// Clear out all cookies and destroy session
if( array_key_exists('HTTP_COOKIE', $_SERVER)){
$cookies = explode(';', $_SERVER['HTTP_COOKIE']);
foreach($cookies as $cookie) {
$parts = explode('=', $cookie);
$name = trim($parts[0]);
setcookie($name, '', time()-1000);
setcookie($name, '', time()-1000, '/');
}
}
session_destroy();
return http_response_code(401);
}会话应该在需要session.php时启动。不过,这似乎并没有发生。访问应用程序时,将显示登录页,但isUserAuthorized.php将抛出一个警告:
警告: session_start():在session.php中读取会话数据失败:用户(路径: /var/lib/php/mod_php/ session )
当我选择Login按钮时,会调用login.php,但是用户会直接进入应用程序,尽管凭据不正确。
login.php
<?php
require_once '../database.php';
require_once 'session.php';
require_once 'ldap.php';
$_SESSION['authenticated'] = false;
//$conn = connect_db();
try {
$data = json_decode(file_get_contents('php://input'));
$username = strtolower($data->username);
$password = $data->password;
// Check domain credentials; return user token if verified
if(ldap_authenticate($username, $password)) {
$_SESSION['authenticated'] = true;
}
else {
echo('Invalid username and/or password!');
return http_response_code(400);
}
}
catch(PDOException $e) {
return http_response_code(400);
}我不完全确定是什么导致了这种奇怪的行为,以及为什么没有创建会话。是否需要显式调用sess_write函数?
更新
我发现从require_once 'session.php'中删除login.php会导致正确的行为。用户可以在提供有效凭据时登录。但是,会话数据仍未写入数据库。知道为什么吗?
发布于 2017-07-18 21:14:06
问题归结到我的会话处理程序上。从PHP 7开始,sess_read函数必须返回一个字符串。这引起了这样的警告:
警告: session_start():在session.php中读取会话数据失败:用户(路径: /var/lib/php/mod_php/ session )
我通过在''还是null时返回null来修正这个问题。
这导致我的sess_write函数在知道何时插入和何时更新时出现问题。我通过更改SQL来修正这个问题。
最后,我将会话处理程序变成一个类,如最后的结果所示:
<?php
require_once ('../database.php');
class CustomSessionHandler implements SessionHandlerInterface{
public function open( $path, $name ) {
return true;
}
public function close( ) {
return true;
}
public function read( $id ) {
$db = dbConn::getConnection();
$stmt = "SELECT session_data FROM session where session_id =" . $db->quote($id);
$result = $db->query($stmt);
$data = $result->fetchColumn();
$result->closeCursor();
if(!$data){
return '';
}
return $data;
}
public function write( $id, $data ) {
$db = dbConn::getConnection();
//Works with Postgres >= 9.5
//$stmt = "INSERT INTO session (session_id, session_data) VALUES (" . $db->quote($id) . ", " . $db->quote($data) . ") ON CONFLICT (session_id) DO UPDATE SET session_data=" . $db->quote($data) . ";";
//Works with Postgres < 9.5
$stmt = "UPDATE session SET session_data=" . $db->quote($data) . " WHERE session_id=" . $db->quote($id) . ";";
$db->query($stmt);
$stmt = "INSERT INTO session (session_id, session_data) SELECT ". $db->quote($id) . ", ". $db->quote($data) . " WHERE NOT EXISTS (SELECT 1 FROM session WHERE session_id=" . $db->quote($id) . ");";
$db->query($stmt);
return true;
}
public function destroy( $id ) {
$db = dbConn::getConnection();
$stmt = "DELETE FROM session WHERE session_id =" . $db->quote($id);
setcookie(session_name(), "", time() - 3600);
$data = $db->query($stmt);
return true;
}
public function gc( $lifetime ) {
$db = dbConn::getConnection();
$stmt = "DELETE FROM session WHERE timestamp < NOW() - INTERVAL '" . $lifetime . " second'";
$data = $db->query($stmt);
return true;
}
}
session_name('PROJECT_CUPSAW_WEB_APP');
$handler = new CustomSessionHandler();
session_set_save_handler($handler, false);
session_start();
ob_flush();https://stackoverflow.com/questions/45108666
复制相似问题