PHP $ _SESSION变量在ionic / angularjs应用程序中不起作用

时间:2019-01-10 10:17:45

标签: javascript php angularjs session

开发环境信息:

  • 本地开发
  • 在我的PC上设置服务器的网络驱动器
  • 通过目录路径访问服务器文件
  • 服务器包含SQL数据库,服务器文件可从其中访问和访问

在应用程序加载时

我已经在页面上设置了ng-init来运行函数$scope.nginit();,该函数将$ _GET请求发送到我的服务器文件login.php:

$http.get(url + "server/login.php", 
            { transformResponse: [] })
.success(function(data, status, headers, config) 
{
    data = JSON.parse(data);
    window.localStorage.setItem("session_id",data.session_id);
})
.error( function(data, status, headers, config) 
{
    console.log("Error: " + data + "; " + status);
});

此内容包含在页面顶部的每个服务器文件中:

// if(isset($_GET['session_id'])) {
//  session_id($_GET['session_id']);
// } else if(isset($_POST['session_id'])) {
//  session_id($_POST['session_id']);
// }

session_start();

include_once "../scripts/masterscript.php";

header("Access-Control-Allow-Origin: *");

$connection = connect_to_database();
try
{
    if($_SERVER['REQUEST_METHOD'] != 'POST')
    {
        setup_form();
    }
    else
    {
        process_form();
    }

    sqlsrv_close($connection);  
}
catch (Exception $e)
{
    exit("Exception $e->getMessage()");
}

这是login.php上的setup_form():

function setup_form()
{
    global $connection;
    header('Content-Type: application/json');
    $user_data = array();

    $user_data["session_id"] = session_id();

    echo json_encode($user_data);   
}

在submitForm()上;用于登录:

它将添加存储在localStorage中的session_id作为参数,以便可以将其设置回PHP会话。它将其设置在PHP文件的顶部,但该部分当前已被注释掉。

我的目的是如果它是管理员用户,然后运行第二个$ http.request并打开一个模式。

$http.post(url + "pages/login.php", data_string,
            {   headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;' }, 
                params : { 'session_id' : window.localStorage.session_id }})
.success(function(data, status, headers, config) 
{
    var data = data[0];

    if(data.is_admin)
    {
        $http.get(url + "server/get_more_info.php", 
                    { params : {'user_id' : data.user_id },
                    transformResponse: [] })
        .success(function(data, status, headers, config) 
        {
            // setup to open a modal
        })
        .error( function(data, status, headers, config) 
        {
        }); 
    }
})
.error( function(data, status, headers, config) 
{
});

由于这是$ _POST请求,它将转到process_form(),这里是:

function process_form()
{
    global $connection;
    header('Content-Type: application/json');
    $user_data = array();

    $data_string = file_get_contents("php://input");
    $data = json_decode($data_string);

    $user_data['status_msg'] = "Error";

    // runs SQL query, grabs user details where email = $data->email
    $UserObj = new User(0,$connection, $data->email); 

    if($UserObj->password == $data->password)
    {
        $user_data['status_msg'] = "OK";
        $user_data['user_id']    = $UserObj->user_id;
        $user_data['user_type'] = $UserObj->user_type;

        if($UserObj->admin_user == 1)
        {
            $user_data['is_admin'] = true;
            $_SESSION['is_admin'] = 1;
        }

        $_SESSION['user_id'] = $UserObj->user_id;
        $_SESSION['user_type'] = $UserObj->user_type;
    }

    unset($UserObj);
    echo json_encode($user_data);
 }

在get_more_info.php

我尝试访问在login.php中设置的会话变量,但它们为空。我打算在SQL查询中使用这些变量:

$user_id = $_SESSION['user_id'];
$admin_user = $_SESSION['admin_user'];
$user_type = $_SESSION['user_type'];

$sql = " select * from info_table where admin_user = ? and user_type = ?";
$params = array($admin_user,$user_type);
$result = sqlsrv_query($connection, $sql, $params);       

while($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC))
{
}

sqlsrv_free_stmt($result);
unset($result);

其他信息

我做了一个var_dump();对于下面的这两个都返回空字符串。

ini_get('session.cookie_httponly');
ini_get('session.cookie_secure');

在Firefox上,出现了第一个对login.php的网络请求,它是GET请求,并且具有设置的$ _COOKIE。似乎可以在Chrome浏览器中使用,但不能在Firefox中使用。我目前正在运行ionic serve --lab。在chrome上,它将继续运行并打开应有的模式,但在Firefox上则不会。

在firefox的网络标签上,用于login.php GET请求,它显示 在响应标头下设置了cookie,但在请求标头上没有与cookie相关的属性。

对于login.php POST请求,其结果与前一个cookie相同,但此请求在网络标签下以OPTIONS方法而不是POST的形式出现。 / p>

问题

  • 最初的问题是,get_more_info.php中的会话变量为空白。这是因为它没有恢复到从$scope.nginit();开始的同一会话。它正在开始一个新的。
  • 提出了存储session_id以便可以恢复到同一会话的想法,这就是我在这里所做的。
  • 最初,我试图通过手动将session_id设置在我的PHP文件的顶部来进行设置,但是提醒我注意这是不需要的,它应该自动执行,而不是自动进行。

2 个答案:

答案 0 :(得分:2)

后端

第一:此位是不必要

if(isset($_GET['session_id'])) {
    session_id($_GET['session_id']);
} else if(isset($_POST['session_id'])) {
    session_id($_POST['session_id']);
}

more_details.php文件开头唯一需要的行是session_start()

如果您看着the documentation for this function,它会清楚地说:

  

session_start()创建一个会话或恢复(*)基于通过GET或POST请求传递或通过cookie传递的会话标识符。

*重点强调

因此,在调用它之后,您可以安全地访问$_SESSION属性。

第二,您需要设置适当的CORS标头。

header("Access-Control-Allow-Origin: http://localhost:8000");
header("Access-Control-Allow-Headers: content-type, authorization");
header("Access-Control-Allow-Credentials: true");

非常重要:无法将Access-Control-Allow-Origin设置为*,否则将失败。使用credentials时,需要明确设置允许的原点。

此外,您需要考虑一个OPTIONS调用,该调用应返回相同的标头。浏览器将在POST请求之前将此调用作为飞行前验证。

出于这个答案的目的,我有一个common.php文件:

<?php
session_start();
header( "Access-Control-Allow-Origin: http://localhost:8000" );
header( 'Content-Type: application/json' );
header( "Access-Control-Allow-Headers: content-type,authorization" );
header( "Access-Control-Allow-Credentials: true" );

if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
    die();
}

另一个文件 one.php

<?php
// one.php
<?php
require 'common.php';

$was_session_set     = $_SESSION['user_id'] ?? 'no session id yet';
$_SESSION['user_id'] = microtime( true );

echo '{"session": "' . $was_session_set . '"}';

die();

另一个 two.php

<?php
require 'common.php';

$user_id = $_SESSION['user_id'] ?? 0;
echo '{"session": "' . $user_id  .'"}';

die();

前端

let app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, $http) {
$http.get("http://localhost:8006/one.php",  { withCredentials: true })
    .then(function (response) {
      $scope.myWelcome = response.data;
      $http.post("http://localhost:8006/two.php", { withCredentials: true })
          .then(function (response2) {
            console.log(response2.data);
          })
    });
});

答案 1 :(得分:1)

要使用cookie(php会话必须使用cookie),您需要告诉您的应用允许它。

使用它进行全局配置,然后应用程序将使用您的cookie并将其重用于其他请求。

.config(['$httpProvider', function($httpProvider) {
   $httpProvider.defaults.withCredentials = true;
}])