【问题标题】:How Should I Implement Implicit Logouts?我应该如何实现隐式注销?
【发布时间】:2011-10-29 14:24:56
【问题描述】:

我的登录系统目前工作如下:

  1. 从 POST 表单中获取用户的用户名和密码。
  2. 对照数据库检查用户名和加盐+散列密码。
  3. 如果身份验证成功,则生成一个长的、随机的字母数字字符串。
  4. 将此字符串存储在 MySQL 中,以及与用户名一起存储在 $_SESSION 变量中。
    • 这与将用户密码放在$_SESSION 中相反。我觉得这为间谍软件进入并窃取用户凭据敞开了大门。
  5. 在每个需要身份验证的页面(例如非敏感帐户设置、仅限会员区域等)上,将 $_SESSION 用户名和字符串与 MySQL 中存储的内容进行对比。
  6. 如果它们匹配,请继续并显示页面。否则,显示登录表单。(?)
  7. 当用户明确注销时,从 MySQL 和 $_SESSION 中删除随机字符串。

我坚持的是当用户隐式退出时如何处理。也就是说,当他/她没有点击网站上的任何“注销”按钮而关闭浏览器窗口时。我很确定我仍然需要从 MySQL 中删除随机字符串,所以以后有人不能使用被盗的 cookie 登录。但是我怎么知道用户什么时候关闭了浏览器窗口呢?

(“记住我”功能暂时无关紧要。)

【问题讨论】:

  • 你的随机字符串本质上就像一个会话。为什么将其存储在 $_SESSION 中而不是作为 cookie?使用会话涉及文件系统访问,并且它在处理请求期间获得对会话文件的排他锁,阻止它处理其他请求,直到请求被分派(或直到 session_write_close() 被调用) - 基本上使一切变慢. PHP 创建的会话 id 已经和你的随机字符串几乎一样了......你最好将它直接存储在 cookie 中。

标签: php session login


【解决方案1】:

我应该如何实现登录会话?

身份验证和会话管理是两个不同的东西,虽然它们紧密相连,但您似乎也在谈论授权。

如果身份验证成功,则生成一个长的、随机的字母数字字符串。

为什么? PHP 已经生成了一个随机标识符(会话 id)。如果您想区分经过身份验证的/未经过身份验证的用户和/或确定哪个用户拥有当前会话,只需将用户名/用户 ID 存储在会话中即可。

将用户密码放入 $_SESSION 变量中

您为什么要这样做 - 一旦您对用户进行了身份验证,您就再也不需要使用密码了。

将 $_SESSION 用户名和字符串与 MySQL 中存储的用户名和字符串进行比较

为什么?除了通过您的代码之外,如何更改会话数据其他?如果您怀疑您的服务器端代码可能被篡改,那么无论您做什么,系统都会不安全。

当用户明确退出时

...您明确地销毁会话。就是这样。

当您从提议中删除冗余时,无需在隐式注销后进行清理。

顺便说一句:您的提案中没有解决许多安全问题,特别是在身份验证尝试后重新生成会话 ID。

【讨论】:

  • +1,但我认为更好的解决方案是使用他的随机字符串作为会话 ID,将其直接存储在 cookie 中,而不是使用有问题的 PHP 的本机会话处理。请参阅我对问题的评论。
【解决方案2】:

您可以在 onclose 事件上使用 ajax 调用来终止会话...从未尝试过,但它应该可以工作:

$(window).unload( function () { 
    // ajax to kill the session 
} );

【讨论】:

  • 我以前从未使用过 Ajax,我想避免向网站添加更多层。
  • 您可以简单地使用new Image().src='remove-session.php' 向服务器发送请求。但它与$.get('remove-session.php') 没有太大区别...基本上,只需以某种方式向服务器发送请求并在处理请求时删除会话。
  • 另外,如果您使用 AJAX,请确保添加一些延迟或使请求同步。否则,浏览器可能会在服务器获取请求之前停止请求。您还可以添加ignore_user_abort(TRUE),这样即使浏览器关闭连接,服务器也会继续处理请求 - 但如果浏览器在完全发送请求之前关闭连接,这将无济于事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 2021-11-08
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 2011-06-07
相关资源
最近更新 更多