在索引页上设置PHP会话以进行XSRF检查

在索引页上设置PHP会话以进行XSRF检查,php,angularjs,session,csrf,Php,Angularjs,Session,Csrf,我遇到了以下有关XSRF令牌的问题 客户:AngularJS 服务器:PHP 当点击index.php时,php生成一个XSRF令牌并将其保存在会话中。 cookie被设置为具有相同的值 AngularJS读取cookie并存储值 在随后的文章中,XSRF令牌作为报头发送,其思想是将存储的会话令牌与发送的报头进行比较 一切似乎都很好,没有任何问题 但是:问题是,PHP无法读取index.PHP中注册的会话,因为从技术上讲,没有重新加载页面!如果我点击F5并重新加载所有内容,那么会话将被很好地读取

我遇到了以下有关XSRF令牌的问题

客户:AngularJS 服务器:PHP

当点击index.php时,php生成一个XSRF令牌并将其保存在会话中。 cookie被设置为具有相同的值

AngularJS读取cookie并存储值

在随后的文章中,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; 
/* Give token to Angular client */
<script>
angular.module("app").constant("CSRF_TOKEN", '<?=$_SESSION['XSRF'];?>'); 
</script>
稍后,也在index.php中:

// Create token and set session
session_start();
$token = hash('sha256', uniqid(mt_rand(), true));
$_SESSION['XSRF']=$token; 
/* Give token to Angular client */
<script>
angular.module("app").constant("CSRF_TOKEN", '<?=$_SESSION['XSRF'];?>'); 
</script>
对服务器的所有请求都被路由到一个公共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-TOKEN自定义头发送,因此我们需要将该值与会话中存储的值进行比较。)


欢迎反馈,因为我不知道这是否足够提供XSRF保护。

您是否在服务器上的$http调用或其他php页面中发布到index.php?如果我理解你的问题,那就是php文件得到一个空会话?如果我理解正确。。。您可以使用PHP生成XSRF令牌变量,并将其放入JS代码中,如果您希望它可用于ajax请求。。。也许你的一些示例代码会有所帮助?没有理由不起作用。在第一个请求中,您创建了一个会话和一个令牌,并将会话cookie与第一个响应一起返回。会话现在存在,所有后续请求都有一个活动会话。我们需要更多的细节来帮助你们。嘿,伙计们,谢谢你们的回复。稍后我将尝试发布一些代码,但基本上我不会发布到同一个index.php文件中。所有Ajax请求都发布到相同的公共php页面。我正在检查会话,但它不在那里。。。。直到重新加载页面。嘿,伙计们,很抱歉占用了你们的时间。它现在对我来说很有效,但有趣的是我并没有太大的改变。我更改了会话变量的名称,突然一切都正常了。。奇怪..嗨,谢谢你的回答。这也是我做这件事的基本方法。顺便说一句,检查http头是否出现的一种更简单的方法是使用$headerToken=$\u SERVER['http\u XSRF\u TOKEN',无需循环检查所有头。还请记住,Angular只在POST、PUT和DELETE请求上发送头,而不是在GETI上发送头。我建议将microtime()作为“随机”生成器,例如,放置用户的ID、IP地址、访问的页面等,将增加复杂性并使猜测XSRF-TOKEN变得更加困难。我还建议通过使用httponly(如果可能)和path参数来最小化cookie的暴露。因此,您不必创建cookie来读取。只需设置一个常量(请参阅我的更新)这是否被认为与使用cookie一样安全?不明白为什么不安全?它被注入AngularJS中,并且只在index.php页面上提供。。。