开发环境信息:
在应用程序加载时
我已经在页面上设置了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>
问题
$scope.nginit();
开始的同一会话。它正在开始一个新的。答案 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;
}])