簡體   English   中英

AngularJS和PHP應用程序中的會話

[英]Sessions in AngularJS and PHP application

我有一個要更新為使用PHP 7的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函數?


更新資料

我發現從login.php中刪除require_once 'session.php'會導致適當的行為。 用戶提供有效的憑據后便可以登錄。 但是,會話數據仍然永遠不會寫入數據庫。 知道為什么嗎?

問題歸結於我的會話處理程序。 從PHP 7開始, sess_read函數必須返回一個字符串。 這引起了警告:

警告:session_start():無法讀取會話數據:session.php中的用戶(路徑:/ var / lib / php / mod_php / session)

我通過在$datanull時返回''解決此問題。

這導致我的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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM