Ada*_*per 5 php session google-chrome session-cookies prerender
我遇到了一些会话功能以及Chrome预取/呈现方式的问题.我试图将一个论坛软件(esoTalk)与自定义laravel 4.3应用程序连接.我有认证事件监听器,导致laravel创建一个php会话(此外还有内置的laravel会话),允许论坛和应用程序共享身份验证详细信息.在访问论坛时,如果用户未登录 - 但此共享信息存在(即用户已登录laravel应用程序),论坛将使用会话中提供的信息登录该用户.
在大多数情况下,这可以正常工作,除了Chromes预取似乎是破坏事物.如果我使用调试器监控论坛,我可以看到,当我输入论坛网址时,但在我点击之前输入chrome将访问论坛.通过调试器,我可以看到它完成了它需要做的所有事情,并且成功登录.作为最后一步,论坛重新生成会话ID以停止劫持.这就是它破裂的地方.看起来chrome忽略了新的会话ID(通过http SetCookie标头发送),这样当我点击Enter时,我会使用原始会话ID进入论坛(并发出一个全新的请求).此ID不存在,因此我设置了一个新的ID,因此失去了我的登录状态.对于用户而言,这看起来就像他们从未登录过.
我已经google了高低,以获得关于如何解决这个问题的建议.我不愿意删除会话ID重新生成,因为它确实用于安全目的.我也无法禁用chrome预取/渲染.总而言之,我似乎有点腌渍.
我创建了一些复制它的代码.虽然它依赖于预渲染(因此你需要通过地址栏多次击中每个文件)
// test1.php
<?php
function regenerateToken()
{
session_regenerate_id(true);
$_SESSION["token"] = substr(md5(uniqid(rand())), 0, 13);
$_SESSION["userAgent"] = md5($_SERVER["HTTP_USER_AGENT"]);
}
// Start a session.
session_set_cookie_params(0, '/');
session_name("SessionBork_Test_session");
session_start();
$_SESSION["SentryUserId"] = '99';
regenerateToken();
header('Content-Type: text/plain');
foreach ($_SESSION as $k => $v) {
echo $k . " = " . $v . "\n";
}
Run Code Online (Sandbox Code Playgroud)
访问test1.php后跟test2.php,你应该看到一堆会话变量输出.一旦预渲染/取出,你就会开始收到破碎的信息.
// test2.php
<?php
function regenerateToken()
{
session_regenerate_id(true);
$_SESSION["token"] = substr(md5(uniqid(rand())), 0, 13);
$_SESSION["userAgent"] = md5($_SERVER["HTTP_USER_AGENT"]);
}
// Start a session.
session_set_cookie_params(0, '/');
session_name("SessionBork_Test_session");
session_start();
if (empty($_SESSION["token"])) regenerateToken();
// Complicate session highjacking - check the current user agent against the one that initiated the session.
if (md5($_SERVER["HTTP_USER_AGENT"]) != $_SESSION["userAgent"])
session_destroy();
// Log in a the user based on the SentryUserId
// ... logging in, setting userId, regenerating session
$_SESSION["userId"] = '10';
regenerateToken();
header('Content-Type: text/plain');
foreach ($_SESSION as $k => $v) {
echo $k . " = " . $v . "\n";
}
if ( ! isset($_SESSION['SentryUserId'])) echo "\n--\nPrerendering brokeded me.";
Run Code Online (Sandbox Code Playgroud)
如果你可以把它连接到IDE中的xdebug或其他东西你应该看到隐藏的prerender命中test2.php(在响应中看起来绝对正确)然后当你按Enter键时它会忘记谁你是.
解决此问题的一种方法是检测预取,而不是在这些负载上生成新的会话 ID。有关在各种浏览器中检测预取的信息,请参阅此 Stack Overflow:HTTP header to detector a preload request by Google Chrome
此外,我认为有更好的方法来防止会话劫持(例如将会话绑定到 IP 地址、浏览器签名等)
此外,您的代码中可能存在第二个错误:调用session_destroy()
会破坏会话并关闭用户的会话。您需要session_start()
先打电话再打电话session_regenerate_id()
。请参阅此处的文档和此处的示例。
归档时间: |
|
查看次数: |
675 次 |
最近记录: |