繁体   English   中英

编码cookie使其不会被欺骗或读取等

[英]Encoding cookies so they cannot be spoofed or read etc

我正在编写一个PHP应用程序。 我想将用户登录信息存储在cookie中,这样用户就无需在每次访问时登录。

我想对它们进行编码或对它们进行模糊处理,以便它们不会被读取或篡改。

做这个的最好方式是什么?

更新:

我不打算将密码存储在cookie中,只是一个用户ID,以便我知道它们是谁,但我想要对其进行编码或加密,这样就没有人可以欺骗其他用户

简短的回答

不要这样做。 从长远来看,你会后悔的。 当然,你可以加密它,但是当有人找出你的加密密钥时会发生什么。 现在你只需将每个人的凭据交给他们(好吧,不是真的,但足够接近)。

更好的方式

而不是存储加密的用户名和密码,为什么不创建随机令牌并使用用户名存储? 你想要一些相当大的东西,所以像sha256哈希就足够了。

$randomToken = hash('sha256',uniq_id(mt_rand(), true).uniq_id(mt_rand(), true));

然后,将其存储在用户旁边的数据库中,并将cookie发送到客户端(我还建议签署令牌以防止篡改:

$randomToken .= ':'.hash_hmac('md5', $randomToken, $serverKey);

现在,当您验证时,首先检查哈希是否匹配:

list($token, $hmac) = explode(':', $_COOKIE['remember_me'], 2);
if ($hmac != hash_hmac('md5', $token, $serverKey)) {
    die('tampered token!');
}

从那里,只需通过令牌查找用户。 如果找到,请记录该用户。

我还建议在每次更改密码时更改令牌。

直接回答你的问题

注意: 请勿在实时生产代码中执行此操作 您永远不能完全信任离开Web服务器的数据。 所以不要暴露你的用户信息。 这不值得。 但是,我确实添加了一些额外的检查(例如签署cookie)以使其更安全,但是你已被警告......

为了对其进行编码,我将使用mcrypt将数据加密到cookie中。 然后,我会创建一个随机盐并将其与用户行一起存储,然后使用该唯一的salt使用hash_hmac对加密数据进行hash_hmac 这样,如果有人拦截了cookie 找出了密钥的密钥,你仍然可以检测到无效的hmac,这样你就可以找到篡改。

function generateCredentialsCookie($user_id, $password) {
    $encrypted = encrypt($user_id.':'.$password, $secretkey);
    $salt = uniq_id(mt_rand(), true);
    $encrypted .= ':'.hash_hmac('sha256', $encrypted, $salt);
    storeSaltForUser($user_id, $salt);
    set_cookie('credentials', $encrypted);
}

function readCredentialsCookie() {
    $parts = explode(':', $_COOKIE['credentials']);
    $salt = array_pop($parts);
    $encrypted = implode(':', $parts); //needed incase mcrypt added `:`
    $raw = decrypt($encrypted, $secretkey);
    list ($user_id, $password) = explode(':', $raw, 2);
    if ($salt == getSaltForUser($user_id)) 
        return array($user_id, $password);
    } else {
        return die('Invalid Cookie Found');
    }
}

注意 - 这是伪代码。 你需要更多安全(例如检查无效值,确保成功解密等)。

不要使用长时间运行的会话!

您应该将会话过期保持在尽可能低的水平(我通常使用30分钟的会话,但有些网站会更低)。 到期时间是在最后一次使用之后,因此只要站点被主动使用就无所谓了。

至于为什么不使用长时间运行会话,这里有一些缺点:

  • DOS(拒绝服务漏洞已创建

    • 磁盘空间 - 每个会话使用相当少的磁盘空间。 但是当你有一个长时间运行的会话时,每个新会话只会增加到之前的总数。 因此,对于长时间运行的会话,有人只需要使用新的会话ID一遍又一遍地访问您的站点,并且突然间您没有磁盘空间(假设一个理智的磁盘)。

    • 文件夹空间 - 每个会话在一个文件夹中占用一个文件。 大多数流行的文件系统会因单个文件夹中的大量文件而变慢。 因此,如果您放置100万个会话文件,读取或写入会话文件将会很慢(非常慢)。 垃圾收集(清理旧文件)非常非常慢(如果它甚至可以运行)。

  • 会话劫持漏洞被打开。 这是因为您在网站上打开的会话越多,就越容易猜出有效的标识符(由于生日攻击 )。 您铺设的会话越少,猜测有效会话就越难。

可能有其他人,但这是一个快速概述。 如上所述,使用签名的remember-me令牌而不是长时间运行的会话。 你会好得多,而且更安全......

将用户数据存储在cookie中是错误的方法。 您应该使用PHP会话 将存储在客户端上的唯一内容将是简单cookie中的会话ID(PHP将自动为您处理)。 它已经是一个加密的字符串。

PHP将跟踪服务器端的用户数据。

这将实现您所描述的预期效果,同时比使用cookie更安全。

绝对在任何情况下都不应该将用户凭据存储在cookie中。 您应该始终假设cookie,因为所有用户输入都不可信任。

几种方法:

如果用户选择“记住我”,则只需在初始化会话之前设置以下内容。

session_set_cookie_params(60 * 60 * 24 * 7); //save cookie session for 7 days

否则,在数据库中存储唯一标记,并查询该标记以查看它是否属于用户,如果是,则填充其会话。

我会推荐第一个选项。

生成16个或更长的加密安全随机数并将其存储在cookie中更简单。 无需加密/解密。 在服务器端检查有效时间有限的情况下使用它(不要依赖于MaxAge或Expires)。 这是一个会话cookie。

这是非常安全的,因为没有关键信息离开服务器。

此技术的缺点是您需要为该会话ID创建数据库索引,并为每个请求执行数据库查找。 对于大多数网站而言,这可能已经足够好了,只要延迟不可察觉且服务器负载可接受。

为了最大限度地减少服务器负载和响应延迟,将用户ID,角色和cookie创建标记存储在安全cookie值中是一个有效选项。 不需要数据库或缓存命中来清除无效请求,如果用户ID是压缩的,则索引会很小并且查找速度更快。 但是,除非您知道自己在做什么,否则不要发明自己的安全值编码。

这种方法的缺点是,如果有人发现了密钥,他就可以伪造cookie。 然后,他可以创建具有不同用户ID的cookie并访问其帐户。 因此,在风险有限且对密钥的访问受到控制的情况下使用此方法。 执行加密/解密和隐藏密钥的专用硬件设备可能是一种解决方案。 但这种情况目前并不常见且昂贵。 它的延迟可能比在缓存中查找随机会话ID更大。 后者是更简单,更安全的解决方案。

使用公钥/私钥来保护cookie中的值,可用于保护私钥。 但要做到这一点要复杂得多,延迟可能与具有简单随机缓存会话ID的系统相当。

另请注意,使用cookie的任何方法都需要使用HTTPS。 否则,中间人或间谍交换数据的人可以轻松获得cookie的副本并冒充用户。

保存前盐饼干。 添加用户代理,ip以扩展安全性。

$cookie_to_save = sha1($pwd . $user_agent . $yourSalt);

在自动登录

if($cookie_saved == sha1($pwd . $user_agent . $yourSalt) ok...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM