PHP;如何将受密码保护的登录安全地存储为cookie?

PHP;如何将受密码保护的登录安全地存储为cookie?,php,security,cookies,Php,Security,Cookies,这是我的PHP代码 <?php $username = "admin"; $password = "admin"; $session = $_COOKIE['session']; $private_key = "!$//%$$//%$&=§$!&%&=§$!&%"; if(isset($_POST['login'])) { if($_POST['username'] == $username && $_POST['password'

这是我的
PHP
代码

<?php
$username = "admin";
$password = "admin";
$session = $_COOKIE['session'];
$private_key = "!$//%$$//%$&=§$!&%&=§$!&%";

if(isset($_POST['login'])) {
    if($_POST['username'] == $username && $_POST['password'] == $password) {
        setcookie("username", $username, time()+(10*365*24*60*60));
        setcookie("session", md5($password.$private_key), time()+(10*365*24*60*60));
        echo "You are are logged in!";
    } else {
        echo "Wrong login!";
    }
}


if(isset($_COOKIE['session'])) {
    if($_COOKIE['username'] == $username && $_COOKIE['session'] == md5($password.$private_key)) {
        echo "You are are logged in!";
    } else {
        echo "Wrong login!";
}
}
?>


<form method="post" action="">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" name="login">
</form>

此代码的作用:当您使用正确的数据登录时,将使用用户名和哈希密码设置cookie。用户名不是秘密,可以明文存储。密码在散列之前与一个神秘字符串组合,以防止有人猜到密码。如果不知道
$private\u密钥
,他就不会成功

重新访问页面时,由于cookie,您已登录

当然,我的剧本并不完美,但是:这是正确的方式吗

没有正确的登录数据,您无法登录。黑客也无法找到密码,因为它与一个神秘的字符串结合在一起


但是黑客可以通过某种方式读取cookie数据,并且通过在浏览器中操纵cookie数据,只能使用cookie数据登录。我怎样才能阻止它呢?

如果您试图实现“在这台计算机上记住我”功能(即会话之上的持久身份验证),那么您将进入一个真正复杂的兔子洞。我建议读到这个话题

总结一下策略:不要将密码存储在cookie中(散列或其他形式)。相反,您将使用随机生成的令牌。具体来说,是一个

长期身份验证(“跨会话记住我”)cookie 页面加载时:

if (!isset($_SESSION['user_id']) && isset($_COOKIE['long_term_auth'])) {
    try {
        $_SESSION['user_id'] = $auth->loginWithPersistentCookie($_COOKIE['long_term_auth']);
    } catch (Exception $ex) {
        // Security error! Handle appropriately (i.e. log the incident).
    }
}
上面的代码段假定
$auth
是示例
身份验证
类的一个实例。它还假定
auth_令牌
的基本表结构(
user_id
指向用户表,
selector
hash
是VARCHAR或文本字段,对
selector
有唯一的约束)

为什么这个代码是安全的?
  • 它将长期身份验证cookie与用户密码分开
  • 代币只允许使用一次
  • 它使用
    random_bytes()
    生成安全令牌
  • 它使用SHA256(而不是MD5)来存储较大的身份验证。代币
  • 它使用
    hash_equals()
    来比较哈希
  • 它只通过HTTPS发送长期身份验证cookie
  • 它使用PHP的内置会话管理功能
为什么问题的代码不安全?
  • 它使用MD5,这不是一个安全的哈希函数
  • 它使用
    =
    而不是
    hash_equals()
    来比较哈希。另见:

此外,对于实际的用户身份验证步骤,您需要使用
password\u hash()
password\u verify()
。这只是描述了“记住我”复选框便利功能的安全实现

为了获得更好的安全性,您可能需要使用和/或之类的方法来防止使用弱密码/泄露密码


您的用户将希望使用密码管理器,如KeePassXC、1Password或LastPass,为您的网站生成/存储他们的密码,这样,如果您试图实现“在这台计算机上记住我”功能,他们就不会使用像
admin
这样的弱密码(也称为会话之上的持久身份验证),您即将进入一个真正复杂的兔子洞。我建议您阅读该主题

总结一下策略:不要将密码存储在cookie中(散列或其他形式)。相反,您将使用随机生成的令牌。特别是一个

长期身份验证(“跨会话记住我”)cookie 页面加载时:

if (!isset($_SESSION['user_id']) && isset($_COOKIE['long_term_auth'])) {
    try {
        $_SESSION['user_id'] = $auth->loginWithPersistentCookie($_COOKIE['long_term_auth']);
    } catch (Exception $ex) {
        // Security error! Handle appropriately (i.e. log the incident).
    }
}
上面的代码片段假定
$auth
是示例
身份验证
类的一个实例。它还假定
身份验证令牌的基本表结构
user\u id
指向用户表,
selector
hash
是VARCHAR或文本字段,对
selector
具有唯一约束)

为什么这个代码是安全的?
  • 它将长期身份验证cookie与用户密码分开
  • 代币只允许使用一次
  • 它使用
    random_bytes()
    生成安全令牌
  • 它使用SHA256(而不是MD5)来存储较大的身份验证令牌
  • 它使用
    hash_equals()
    来比较哈希
  • 它只通过HTTPS发送长期身份验证cookie
  • 它使用PHP的内置会话管理功能
为什么问题的代码不安全?
  • 它使用MD5,这不是一个安全的哈希函数
  • 它使用
    =
    而不是
    hash_equals()
    来比较哈希。另请参见:

此外,对于实际的用户身份验证步骤,您需要使用
password\u hash()
password\u verify()
。这只是描述了“记住我”复选框便利功能的安全实现

为了获得更好的安全性,您可能需要使用和/或之类的方法来防止使用弱密码/泄露密码


您的用户将希望使用密码管理器,如KeePassXC、1Password或LastPass,为您的网站生成/存储他们的密码,这样他们就不会使用弱密码,如
admin

不,这不是正确的方法。无论是否加密,都不要将密码发送回用户。不要将其保存为cookie,加密也可以不保存。不要将其以纯文本形式保存在数据库中,请使用密码\u哈希和密码\u验证。要让登录的用户存储一个刷新(新创建)的授权令牌每次访问时。@Jeff但是如果黑客有这个授权令牌怎么办?他不能在自己的浏览器中使用它吗?是的,他会-一次。但是他不会得到用户的密码或你的私钥。下次真正的用户在线时,他就出去了(除非他更改了密码)。如果没有密码,他就不能使用
if (!isset($_SESSION['user_id']) && isset($_COOKIE['long_term_auth'])) {
    try {
        $_SESSION['user_id'] = $auth->loginWithPersistentCookie($_COOKIE['long_term_auth']);
    } catch (Exception $ex) {
        // Security error! Handle appropriately (i.e. log the incident).
    }
}