PHP 发生快速导航时未选中会话

PHP sessions unchecked when rapid navigation occurs

我有一个按以下方式形成的会话:

function sec_session_start() {
$session_name = 'primary_session';
$secure = false;
$httponly = true;
if (ini_set('session.use_only_cookies', 1) === FALSE) {
    header("Location: /error?e=1");
    exit();
}
$cookieParams = session_get_cookie_params();
session_set_cookie_params(3600,$cookieParams["path"],$cookieParams["domain"],$secure,$httponly);
session_name($session_name);
session_start();
session_regenerate_id(true);
}

我通过在我的索引页面上添加 sec_session_start(); 在我的所有页面上使用它,这需要正确的文件,具体取决于我正在访问的页面。

它在慢速导航下工作得很好。

但是,当发生快速导航点击时,出于某种原因它未选中,并且用户已注销。 怎么来的?

这是我快速按下的按钮。注意:它还会将页面从 www.example.com 更改为 www.example.com/users,然后重复 www.example.com/users 直到会话中断。

这是大约 2-3 次快速点击后的结果。每秒按 1-2 次时工作正常,最大值

我试过不把它当作一个函数来使用,把它放在页面的绝对顶部没有成功。

错误似乎是session_regenerate(true)

此命令生成一个新的会话 ID。如果设置为 true,该参数将删除旧的 session 文件。这段代码中设置为true,所以session创建启动后直接关闭删除。

我认为它只出现了几次,因为该命令是在 session_start() 被调用并且输出已经开始之后被调用的。

尝试将参数更改为 false。 为了正确使用 session_regenerate() 查看 this question.

您似乎在每次加载页面时都丢弃了旧的 session ID。这是不必要的、低效的,并且会导致损坏。

如果您快速连续导航两次,可能会发生以下情况:

  • 第一个请求到达服务器并开始执行您的 PHP,导致 session_regenerate_id(true) 破坏旧的 session
  • 这将导致来自 PHP 脚本的响应包含 Set-Cookie: sessionid=something header,要求浏览器更新其 cookie 以指向新的 session
  • 但是浏览器还没有收到脚本的响应
  • 你点击第二次
  • 浏览器放弃现有请求。任何 Set-Cookie header 现在都不会被收听了
  • 浏览器向您的服务器发出新请求。浏览器对新 session 一无所知,因此它包含旧 session cookie
  • 您的脚本看到了旧的 session cookie,它没有指向任何内容,因此用户必须启动一个新的 session 未登录的

如果您有一个基于在 session 中存储同步器令牌的 anti-Cross-Site-Request-Forgery 系统,那么在每次加载页面时重新生成 session ID 也会使您使用的任何表单无法操作当浏览器在站点上同时打开多个选项卡时,或者当用户使用“后退”按钮导航时。

只有当与 session 关联的身份验证更改时(主要是在用户登录时),您才应该 session_regenerate_id

更改 session ID 不会阻止 session 固定;它只是当 session 固定已经通过其他方式发生时的缓解措施(例如,邻居子域上的易受攻击的应用程序将 cookie 注入共享 parent 域)。

如果您没有更改 session ID,那么已经获得 session 固定的攻击者可以通过给您 session 她已经生成并知道的 ID,并让您使用该 session 登录,将其升级为经过身份验证的 session。当您更改身份验证边界上的 session ID 时,这是不可能的;她现在能做的最糟糕的事情就是将您推入 session,您意外地以她的身份登录。这并不理想,但通常这构成了一种破坏性小得多的攻击。