什么是在PHP中进行用户身份验证的最佳方式?

17 php authentication login

我一直在写2个cookie,1个包含用户ID,第2个包含密码的SH1哈希的1/2(盐渍).它的工作方式是不言而喻的.

我意识到我并没有以最安全的方式做到这一点.这是一个更好的方法吗?最好使用单个身份验证cookie.

还有,使用"难以计算哈希"是否有意义?我的意思是,使用bcrypt,或者用漩涡对每个项目进行散列10,000次,使其成为(相对)慢的散列函数(200 ms vs小于1 ms只是简单的SHA1)?我的意思是,如果有人违反了你的数据库并获得了哈希......那么还有什么需要保护,因为你的所有数据都在同一个数据库中(除非你有某种分散设置,我不这样做).

Mar*_*ius 20

使用Sessions.将会话ID存储在cookie中,并将用户的状态存储在服务器端(loggedIn,userId,IP).

要阐明您需要存储在会话数组中的内容:

  • loggedIn:关于用户是否登录的布尔变量.您可以为多个会话重复使用相同的Cookie,以便下次访问您的网站时记住用户的用户名等.
  • userId:数据库中用户的uniqe id.使用此选项可获取有关用户的更多信息,例如用户名,电子邮件等.用户注销后,也可以将其保存在会话数组中.
  • IP:为了防止有人窃取会话ID并使用它,您也存储用户的IP.这是可选的,因为有时您希望允许用户漫游(例如,stackoverflow允许我使用笔记本电脑移动而不会在IP更改时将我退出).
  • lastPing:上次看到用户的时间戳.这可以用来代替cookie的到期日期.如果还存储会话的生命周期,则可以由于不活动而将用户注销.这意味着会话ID cookie可以存储在用户计算机上很长一段时间.

当用户注销或由于不活动而注销时,您只需设置loggedIn为false.当用户使用正确的用户名和密码登录时,您设置loggedIn为true并更新其他字段(userId,IP,lifetime).当用户加载页面时,您将检查lastPing当前时间和lifetime,以及更新lastPing或注销用户.

会话数据可以存储在文件系统中或数据库中.如果存储在数据库中,则userId是用户记录的外键,或者所有数据都可以放在用户记录中.

哈希

多次重复一次值不是一个好主意,因为你降低了安全性.而是使用salt,将静态salt(例如页面名称)与用户的用户名以及密码组合在一起.花费很长时间的哈希并不比快速哈希更好,导致大摘要的哈希比导致短摘要的哈希(由于暴力)更好.对于普通站点(IE,不是银行或秘密军事组织),使用SHA1应该足够好.

  • 如果一个数据库查询带给你的应用程序,那么你有一个问题,我相信这里有几个想要的. (5认同)

lee*_*ers 5

目前,用于识别用户的唯一令牌是用户名 + 加盐密码哈希值的 1/2。该令牌是静态的,这意味着它将在每个请求中保持不变,直到用户更改密码为止。这意味着如果我想冒充系统中的用户,我只需要捕获/拦截令牌一次。(除非您在创建存储在 cookie 中的哈希值期间将熵引入到令牌中)。由于大多数用户很少更改密码,攻击者将拥有相当于未过期的令牌来访问用户帐户。

\n\n

更好的解决方案是使用 PHP 的会话机制并session_regenerate_id在每个请求上调用来不断更新令牌。这样做使得会话劫持几乎不可能,尤其是通过具有 IP 地址/范围限制的 SSL 连接。

\n\n
\n

目前,我为登录的用户进行了 0 次数据库调用(除了登录期间或某些内容发生更改时)。我希望\n它保持这样... \xe2\x80\x93 Yegor 7\n 分钟前

\n
\n\n

PHP 会话数据默认存储在文件系统中,因此您不会使用内置会话机制进行额外的数据库调用。

\n\n
\n

另外,使用“hard\n 计算哈希值”有什么意义吗?我的意思是,\n 使用 bcrypt,或者使用 Whirlpool 对每个项目进行 10,000 次散列,使其成为一个(相对)较慢的散列函数\n(200 毫秒 vs 小于 1 毫秒的普通 SHA1)?

\n
\n\n

对字符串进行 10,000 次哈希处理并不会对其进行一次哈希处理安全性提高 10,000 倍。使用 SHA1 或 Whirlpool 等良好的单向加密进行一次哈希处理。

\n\n
\n

我的意思是,如果有人破坏了您的数据库并获取了哈希值......还有什么需要保护的,因为您的所有数据都在同一个数据库中(除非您有某种去中心化的设置, \n 我不知道)。

\n
\n\n

对密码散列加盐可以保护它们免受彩虹表攻击。目前,使用彩虹表破解加盐密码即使不是不可能也是非常困难的。

\n