最近发现维护的CoffeePHP社区关闭了网页之后再次进入的时候需要再次登录,所以想要做一个「 记住我」的功能。
上网上查了一下,很多是直接把用户名和加密过的密码放到cookie里,然后验证用户名和密码与数据库里的是否相同,这样的话,功能是可以实现,但安全性就不敢苟同了。
然后参考Laravel的Auth,实现了一个安全性相对较高的「 记住我」功能。
基本思路就是使用用户标识(user_id或user_name)+登录标识(token),将他们存到用户浏览器的Cookie里,把token存入数据库,然后相比较是否相同即可。
1.在用户第一次登录的时候,将user_id和token存入cookie,token存入用户表。1
2
3
4
5
6
7
8
9//用户登录了,并且拿到了用户信息
$_SESSIONS['auth'] = $user; //使用session存储用户的信息
$rememberToken = md5(uniqid(rand(), TRUE));//使用不可逆算法生成token
$rememberMe = $userId . ':' . $rememberToken;
//对$rememberMe进行可逆的加密,PHP里有base64、mcrypt、openssl等,这里使用openssl
$pass = '1234';
$method = 'des-ede3';
$encryptRememberMe = openssl_encrypt($rememberMe, $method, $pass);
setcookie('remember_me', $encryptRememberMe,time() + 15 * 86400 );//将加密过的字符串放入cookie,并设置超时时间,建议不要超过一个月
2.用户每次打开网站时验证登录状态1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 获取cookie
$rememberMeCookie = $_COOKIE["remember_me"];
if (!isset($_SESSION['auth']) && $rememberMeCookie) {
// 解密获取cookie真正的值
$pass = '1234';
$method = 'des-ede3';
$rememberMe = openssl_decrypt($rememberMe, $method, $pass);
list($userId, $rememberToken) = explode(':', $rememberMe);
//根据用户id从数据库获取用户信息,记得要对$rememberMe进行防sql注入,以防别人猜出存入cookie值的加密算法,假设用户信息为$user的数组
if (!empty($user) && $user['remember_token'] === $rememberToken) {//比较token是否相同
//设置用户的session
$SESSIONS['auth'] = $user;
}
}
3.用户退出登录时记得删除cookie1
2
3
4
5//删除cookie
setcookie('remember_me', '', time() - 3600 );
//再删除session
unset($_SESSION['auth']);
session_destroy();
至此就完成了「 记住我」的功能,cookie使用了可逆的加密,就算被别人破解了,后面还会去验证token是否与数据库里面的一致,这样安全性相对而言就高一些了。