问题
I have run in to the following problem regarding XSRF tokens.
Client: AngularJS Server: PHP
When the index.php is hit, PHP generates an XSRF token and saves it in a session. A cookie is set with same value.
AngularJS reads the cookie and stores the value.
On subsequent POSTS, the XSRF token is sent as a header, and the idea is to compare the stored session token to the sent header.
Everything seems fine, no problems whatsoever.
BUT: the issue is, that PHP cannot read the session registered in index.php, because technically there have been no page reloads! If I hit F5 and reloads everything , the session is read nicely.
How can I set the XSRF Session token on index.php and have it available for subsequent ajax requests from the client?? I'm pulling out my hair on this one... appreciate feedback.
UPDATE
After changing the session identifier name, everything suddenly worked!
In index.php:
// Create token and set session
session_start();
$token = hash('sha256', uniqid(mt_rand(), true));
$_SESSION['XSRF']=$token;
Later, also in index.php:
/* Give token to Angular client */
<script>
angular.module("app").constant("CSRF_TOKEN", '<?=$_SESSION['XSRF'];?>');
</script>
Note that I'm not using a cookie, instead I set a constant which is then made available to the .run method in Angular:
in Angular:
angular.module('app').run(['CSRF_TOKEN','$http',function(CSRF_TOKEN,$http) {
$http.defaults.headers.common['CSRF_TOKEN'] = CSRF_TOKEN;
All requests to the server are routed to one common php file. The file checks if the header is set, and compares the two tokens:
// Only POST requests are checked (I don't use PUT/DELETE)
if($_SERVER['REQUEST_METHOD']=="POST"){
session_start();
$headerToken = $_SERVER['HTTP_CSRF_TOKEN'];
$sessionToken = $_SESSION['XSRF'];
if($headerToken!=$sessionToken){
header('HTTP/1.0 401 Unauthorized');
exit;
}
}
回答1:
This is what I'm doing in my PHP/AngularJS projects:
index.php
session_start();
if (!isset($_SESSION['XSRF-TOKEN'])) {
$uniqueValues = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']); //add more/less/any "unique" values, see comments
$_SESSION['XSRF-TOKEN'] = sha1(uniqid(microtime() . $uniqueValues, true));
setcookie('XSRF-TOKEN', $_SESSION['XSRF-TOKEN']);
}
any script called by AngularJS $http:
(AngluarJS uses the value of the cookie XSRF-TOKEN and will send it in every request as X-XSRF-TOKEN custom header, so we need to compare this value to the value stored in the session.)
function verifyXSRF() {
/*
$headers = apache_request_headers();
$headerToken = "";
foreach ($headers as $header => $value) {
if ($header == "X-XSRF-TOKEN") {
$headerToken = $value;
break;
}
}
*/
//more efficient, see comments
$headerToken = $_SERVER['HTTP_X_XSRF_TOKEN'];
if ($headerToken != $_SESSION['XSRF-TOKEN']) return false;
return true;
}
session_start();
if (!verifyXSRF()) die("XSRF error");
Feedback welcome as I don't know exactly if this is enough XSRF protection.
来源:https://stackoverflow.com/questions/20196737/setting-php-session-on-index-page-for-xsrf-check