【问题标题】:Securing PHP remember me using a client side cookie使用客户端 cookie 保护 PHP 记住我
【发布时间】:2012-09-02 11:32:21
【问题描述】:

我知道这个问题可能会被问很多次,但他们中的大多数人建议你存储 ip+username+password 并散列整个事情并进行比较,相反我为我的网站想出了一个不同的解决方案,我想做点什么像这样:

我正在使用 session 来存储用户名、用户 ID、时区偏移等,现在假设我们说用户登录并且他检查了 记住我,我将设置会话,然后我将生成一个变量uniqueid 持有随机的 12-13 位 ID,设置后我将在他的浏览器上使用这个唯一 ID 和用户名创建一个 cookie,并将其存储在我的数据库中,当他回来时,我将检查该 id 和用户名 cookie 是否是设置如果是而不是选择用户名,从用户名=cookie用户名的数据库中记住meid,然后再次设置会话并将他扔到主页上,否则重定向到登录页面..

如果他注销,我将删除所有 cookie,并在他选择记住并登录后更新唯一值...

这样做有什么问题吗?还是更好的方法?我不希望密码保存在 cookie 中,即使是在散列状态下也是如此。或者我在做什么是完美的?

【问题讨论】:

    标签: php mysql cookies


    【解决方案1】:

    因此,据我了解您的描述,当用户登录(并希望保持永久登录状态)时,您可以执行以下操作:

    • 创建一个随机令牌。
    • 将随机令牌保存在该用户的用户数据库记录中(或保存在包含用户名和令牌的单独表中)。
    • 在包含用户名和令牌的用户浏览器上设置 cookie。

    当用户返回并且没有活动会话,但确实设置了上面的 cookie 时,您在数据库中查找他们的用户名。如果数据库包含该用户的“记住我”令牌,并且该令牌与 cookie 中的令牌匹配,则您为该用户创建一个新会话。

    当用户注销时,您会从他们的浏览器中删除 cookie,并从数据库中删除令牌。


    如果是这样,这是一个非常安全的设计,只要令牌足够长并且由安全的随机数生成器生成(如 Unix 上的 /dev/urandom)。您说您的令牌是“12-13 位长”,相当于 40 位多一点;这有点偏低,我建议至少两倍。另外,您没有说 如何 生成令牌;仅使用 PHP 的 randmt_rand 并不安全,因为它们的输出可能是可预测的。

    我还建议进行两项改进:首先,在将令牌存储到数据库之前对其进行哈希处理(任何加密哈希函数都可以,例如 SHA-1 — 使用长随机令牌,您不需要任何特殊的密码哈希函数,例如PBKDF2) 以便设法复制数据库的攻击者不会获得所有令牌。其次,在数据库中包含令牌的到期日期,以便单个被破坏的令牌不会永远保持有效。

    【讨论】:

    • 回答我在找什么,完美,这是简单的解释,顺便说一句,我使用 mt_rand 和 rand 来生成 10 位随机用户 ID,所以我可以使用 mt_rand 并使用 sha1 和散列该值将此值存储在我的数据库中,也存储在 cookie 中...谢谢 ;)
    • mt_rand 的输出进行哈希处理并不会降低其可预测性:如果您可以预测哈希的输入,您就可以预测输出。 (它可能让攻击者更难通过观察输出来推断状态,但这在很大程度上取决于散列是如何完成的。)你应该使用例如openssl_random_pseudo_bytes 代替。
    • 谢谢,但除非我让我的网站流行起来,否则我不会这么保护它,直到现在 jsut crypting mt_rand 可以工作;) 再次感谢你,这是一个简单的解释,我授予+1 用于提及哈希令牌,所以现在在哈希令牌之后,字符串的长度将是 40 位长(默认为 SHA1)
    • 对我来说,这听起来很像“在船上有更多乘客之前,我不会堵住我船上的泄漏点。”从一开始就做到这一点并没有困难得多,与你必须做的工作相比,无论如何都要用mt_rand 来处理它。但是,嘿,无论你的船漂浮(或不漂浮)...... :)
    • 哈哈太酷了,我正在建造一艘大船,你很快就会得到一张票……;) 所以我的方法或多或少是正确的,只是我需要 crpyt .. .
    【解决方案2】:

    您永远不必在 cookie 中存储用户名和/或密码。您只需要存储一个唯一标识符(随机生成),可以与数据库中的哈希会话标识符进行比较。

    【讨论】:

    • 是的,这就是我的意思,说一个唯一的 ID/散列的 40 位字符串,我将作为一个 rememberme_id 字段存储在我的数据库中,当他回来时,我会比较对吗?顺便说一句,如果,如果碰巧有 2 个用户共享一个共同的散列 ID,比什么?将用户名保存在不同的 cookie 中是否更好,以便我可以比较 username=username 和 rememberme_id=hashed id 而不是通过 else 失败
    • 无论如何,您都需要在每个请求上查找有效的会话 ID。选项“记住我”只应在会话中添加标志以定义更长的到期时间;
    • 抱歉,我没有到这里要标记什么?假设如果我使用 session_id 获取会话 ID,那么接下来会发生什么?你能通过编辑你的答案来解释我吗?
    • 不要为此使用 PHP 内置会话。您需要使用自己的会话系统(cookie + 数据库),以便完全控制过期时间。
    • 简而言之,我将制作一个 sessionid cookie 并将该 id 存储在我的数据库中,当他回来时,我将检查该 cookie 是否存在,如果是,我将与数据库进行比较设置会话变量并将他重定向到他的主页或者登录页面对吗?
    猜你喜欢
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 2015-12-02
    • 2012-08-30
    相关资源
    最近更新 更多