我遇到了以下关于XSRF令牌的问题。
客户:AngularJS服务器:PHP
当index.php被命中时,php生成一个XSRF令牌并将其保存在会话中。cookie设置为具有相同的值。
AngularJS读取cookie并存储值。
在随后的POSTS中,XSRF令牌作为标头发送,其思想是将存储的会话令牌与发送的标头进行比较。
一切看起来都很好,没有任何问题。
但是:问题是,PHP无法读取在index.PHP中注册的会话,因为从技术上讲,还没有重新加载页面!如果我点击F5并重新加载所有内容,会话就会很好地阅读。
如何在index.php上设置XSRF会话令牌,并使其可用于客户端的后续ajax请求??我在这上面拔头发。。。感谢反馈。
更新
更改会话标识符名称后,一切都突然正常了!
在index.php中:
// Create token and set session
session_start();
$token = hash('sha256', uniqid(mt_rand(), true));
$_SESSION['XSRF']=$token;
稍后,也在index.php:中
/* Give token to Angular client */
<script>
angular.module("app").constant("CSRF_TOKEN", '<?=$_SESSION['XSRF'];?>');
</script>
请注意,我没有使用cookie,而是设置了一个常量,然后该常量可用于Angular中的.run方法:
在Angular中:
angular.module('app').run(['CSRF_TOKEN','$http',function(CSRF_TOKEN,$http) {
$http.defaults.headers.common['CSRF_TOKEN'] = CSRF_TOKEN;
所有到服务器的请求都被路由到一个通用的php文件。该文件检查是否设置了标头,并比较两个令牌:
// 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;
}
}
这就是我在PHP/AngularJS项目中所做的:
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']);
}
AngularJS$http:
调用的任何脚本(AngluarJS使用cookie XSRF-TOKEN的值,并将其作为X-XSRF-TOK自定义标头在每个请求中发送,因此我们需要将该值与会话中存储的值进行比较。)
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");
欢迎反馈,因为我不知道这是否足够XSRF保护。