首先,只需跟踪是否有人登录。之后,我们将处理“记住我”功能。
要知道是否有人登录,只需查看$_SESSION数组即可。里面的所有东西都是因为你之前把它放在那里的。因此,在处理登录表单时,如果用户名和密码正确,那么您将用户名、用户 ID 或其他任何内容存储在会话 ( $_SESSION['username'] = $username;) 中。
每当用户加载任何页面时,您只需检查
if (isset($_SESSION['username'])) {
// $_SESSION['username'] is logged in
} else {
// nobody is logged in
}
没有必要将密码存储在$_SESSION(实际上,出于安全目的,最好不要将其存储在数据库中以外的任何地方)。
现在,“记住我”功能......首先,一些注意事项:
- 任何用户都可以修改其浏览器的 cookie,因此您需要确保发送到应用程序的 cookie 未被篡改。
- 用户可以在公共计算机(图书馆等)上进行检查,因此您需要一个系统来使其无效。
- 如果用户退出您的应用程序,则必须删除记住他/她的 cookie。
对于第一点,假设您在 cookie 上存储要“记住”的用户的用户名(非常不安全!!)。这意味着,如果任何用户为您的 Web 应用程序创建了一个包含“joe”内容的 cookie,您的应用程序将认为该用户 joe 已在该计算机中被记住,因此授予该攻击者访问权限,就好像他/她是 joe。因此,我们需要以某种方式加密/散列 cookie。
对于第二点,在某些计算机上使“记住我”无效,我们将以某种方式使用密码。如果某个用户想要使他/她可能选中“记住我”复选框的所有计算机无效,他/她所要做的就是更改他/她的密码。这也意味着如果他/她更改了他/她的密码,出于同样的原因,他/她的所有保存的登录信息都将失效。但安全总比后悔好...
因此,当您处理登录并且用户名和密码正确,并且选中“记住我”选项时,除了将用户名保存在会话中之外,您还存储了用户名和密码的哈希值(如果您将)在您发送给用户的 cookie 中。此外,您需要将用户名以纯文本(或以可逆方式加密)存储在 cookie 中,以了解哪个用户正在尝试通过 cookie “登录”,并检查 cookie 中用户名和密码的哈希值数据库中的用户名和密码。如果该检查是正确的,那么您将用户名存储在会话中并且不再检查该用户的 cookie(至少对于该会话)。
因此,总体而言,您的代码可能如下所示:
登录.php
if (check_login($_POST['username'], $_POST['password'])) {
// login correct
$_SESSION['username'] = $_POST['username'];
if (isset($_POST['remember_me'])) {
// we hash the password because we **NEVER** store it in plain text anywhere
// so when we would like to check if the cookie value is correct, we will not
// be able to do so if the hash in the cookie was done from the plaintext
// password.
$value = sprintf('%s:%s', $_POST['username'], md5($_POST['username'].hash_password($_POST['password'])));
setcookie('rememberme', $value);
}
redirect('/your/home/page.php'); // view Post/Redirect/Get design pattern
} else {
// login incorrect, show error message and whatever...
}
在每个 php 文件的开头(或者更好的是,在包含文件中以引导您的应用程序)
if (isset($_SESSION['username'])) {
// $_SESSION['username'] is logged in, proceed as you wish
} else if (isset($_COOKIE['rememberme'])) {
// this user has checked the remember me feature some time ago in a previous login.
// let's check if it is valid.
list($username, $hash) = explode(':', $_COOKIE['rememberme']);
// we need to get the password hash stored for this user (remember you **NEVER** store passwords in plain text
$pwd_hash = obtain_password_hash_from_username($username);
if ($hash == sprintf('%s:%s', $username, md5($username.$pwd_hash))) {
// yeah, the user remembered is correct. We'll save it to the session to not do this shit again
$_SESSION['username'] = $username;
} else {
// the cookie value is not correct so maybe an attacker is trying to fool us,
// or the user changed his password. Whatever it is, we remove the cookie
// because it's no longer valid
setcookie('rememberme', '', time() - 3600);
}
} else {
// this user is neither logged in nor "remembered"
}
散列用户密码的方法取决于您。您可能喜欢纯 md5 或 sha、salted md5 或 sha(更好)或一些耗时的方法,如河豚(推荐)。我使用普通的 md5 对 cookie 进行哈希处理,但您可以选择前面描述的任何方法。
我想就是这样。