我遇到了一些与会话功能和Chrome预读/渲染方式有关的问题。我正在尝试将一个论坛软件(esoTalk)与一个自定义的Laravel 4.3应用程序进行接口连接。我有认证事件侦听器,导致Laravel创建了一个PHP会话(除了内置的Laravel会话),该会话允许论坛和应用程序共享身份验证详细信息。在访问论坛时,如果用户未登录但存在此共享信息(即用户已在Laravel应用程序上登录),则论坛将使用会话中可用的信息登录该用户。
大部分情况下这很好用,但Chrome的预读似乎破坏了一切。如果我使用调试器监视论坛,在输入论坛网址之前,但在按回车键之前,Chrome将访问论坛。通过调试器跟踪,我可以看到它做了所有必要的工作,并且成功登录了。作为最后一步,论坛重新生成会话ID以防止劫持。这就是它出问题的地方。看起来Chrome忽略了新的会话ID(通过HTTP SetCookie标头发送),因此当我按回车键进入论坛(并发出一个全新的请求)时,使用原始会话ID。这个ID不存在,所以我被设置一个新的ID,因此失去了我的登录状态。对于用户来说,这看起来就像他们从未登录过一样。
我已经高度低地搜索了建议,以解决如何解决此问题。我不愿删除会话ID生成,因为它确实起到了安全作用。我也不能禁用Chrome的预读/渲染。总之,我似乎陷入了一个困境。
我创建了一些代码来复制此操作。虽然它依赖于预渲染的启动(因此您需要通过地址栏多次访问每个文件)。
如果您能在IDE或其他工具中将它与xdebug连接起来,您应该会看到对test2.php的隐藏预渲染命中(在响应中看起来绝对正确),然后是当您按下回车键时的随后实际命中,此时系统会忘记您的身份。
大部分情况下这很好用,但Chrome的预读似乎破坏了一切。如果我使用调试器监视论坛,在输入论坛网址之前,但在按回车键之前,Chrome将访问论坛。通过调试器跟踪,我可以看到它做了所有必要的工作,并且成功登录了。作为最后一步,论坛重新生成会话ID以防止劫持。这就是它出问题的地方。看起来Chrome忽略了新的会话ID(通过HTTP SetCookie标头发送),因此当我按回车键进入论坛(并发出一个全新的请求)时,使用原始会话ID。这个ID不存在,所以我被设置一个新的ID,因此失去了我的登录状态。对于用户来说,这看起来就像他们从未登录过一样。
我已经高度低地搜索了建议,以解决如何解决此问题。我不愿删除会话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";
}
访问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.";
如果您能在IDE或其他工具中将它与xdebug连接起来,您应该会看到对test2.php的隐藏预渲染命中(在响应中看起来绝对正确),然后是当您按下回车键时的随后实际命中,此时系统会忘记您的身份。