Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/authentication/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Authentication “持续”的竞争条件;“记住我”;曲奇饼_Authentication_Cookies_Login_Race Condition - Fatal编程技术网

Authentication “持续”的竞争条件;“记住我”;曲奇饼

Authentication “持续”的竞争条件;“记住我”;曲奇饼,authentication,cookies,login,race-condition,Authentication,Cookies,Login,Race Condition,根据,您不应允许“记住我”令牌被多次使用: 持久性cookie适用于单个登录。确认身份验证后,用于登录的随机数将失效,并分配一个全新的cookie。标准会话管理处理会话生命周期内的凭据,因此新分配的cookie在下一个会话之前不会被检查(此时,它也将在使用后失效) 然后,如果用户同时访问您站点上的多个URL,您如何处理竞争条件?我现在确实遇到了这个问题 假设两个请求同时从浏览器发送到服务器。请求不包含会话cookie,但包含相同的“记住我”cookie。其中一个请求将在另一个请求之前得到处理,并

根据,您不应允许“记住我”令牌被多次使用:

持久性cookie适用于单个登录。确认身份验证后,用于登录的随机数将失效,并分配一个全新的cookie。标准会话管理处理会话生命周期内的凭据,因此新分配的cookie在下一个会话之前不会被检查(此时,它也将在使用后失效)

然后,如果用户同时访问您站点上的多个URL,您如何处理竞争条件?我现在确实遇到了这个问题

假设两个请求同时从浏览器发送到服务器。请求不包含会话cookie,但包含相同的“记住我”cookie。其中一个请求将在另一个请求之前得到处理,并将得到一个带有经过身份验证的会话cookie和重新生成的“记住我”cookie的响应

第二个请求中的“记住我”令牌现在无效,并在服务器上生成另一个会话ID。此请求失败,因为无法对用户进行身份验证


我已经想出了一些可能的解决办法,但没有一个看起来很好。我遗漏了什么吗?

老问题,但我到处都找不到答案。
我也有同样的问题。我的解决方案是将旧令牌存储在数据库中,如果找不到主令牌,则将其用作备用令牌。但我确保旧令牌只在短时间内有效,比如令牌更改后的几秒钟。然后,我只在上次更新后经过一段时间后才更改令牌,否则会出现令牌连续更改多次的情况。

为了详细说明vangoz的答案,我要补充一点,也必须采用某种锁定机制。在这里考虑PHP ISH伪代码:

if (isFallback($token)) {
  // Log the user in
} else {
  // Usual processing
  // If token has to be updated, save old token as fallback for a few seconds
}
当存在并发请求时,它们可能都在else分支中结束,一个请求将导致更新,另一个将导致令牌无效。我解决这个问题的方法是使用一个命名锁(以所讨论的
$token
命名)来包装else分支。此外,除了一个并发请求外,所有并发请求都将无法获取锁,在这种情况下,我们会稍微休眠一段时间,然后重试(重试后,我们会发现该令牌已成为回退令牌)


我希望这些注意事项会有用。

我开始意识到问题是由于http是无状态的。如果“记住我”标记没有立即失效,响应仍将返回不同的会话(浏览器将用最后一个会话覆盖旧会话)。
if (isFallback($token)) {
  // Log the user in
} else {
  $couldLock = lock($token);
  if (!$couldLock) {
    usleep(10000);
    // Retry, possibly a recursive call
  } else {
    // Usual processing
    // If token has to be updated, save old token as fallback for a few seconds
    unlock($token);
  }
}