PHP安全编程:记住登录状态的安全做法
永久登录指的是在浏览器会话间进行持续验证的机制。换句话说,今天已登录的用户明天依然是处于登录状态,即使在多次访问之间的用户会话过期的情况下也是这样。永久登录的存在降低了你的验证机制的安全性,但它增加了可用性。不是在用户每次访问时麻烦用户进行身份验证,而是提供了记住登录的选择。
据我观察,最常见的有缺陷的永久登录方案是将用户名和密码保存在一个cookie中。这样做的诱惑是可以理解的——不需要提示用户输入用户名和密码,你只要简单地从cookie中读取它们即可。验证过程的其它部分与正常登录完全相同,因此该方案是一个简单的方案。
不过如果你确实是把用户名和密码存在cookie中的话,请立刻关闭该功能,同时阅读本节的余下内容以找到实现更安全的方案的一些思路。你将来还需要要求所有使用该cookie的用户修改密码,因为他们的验证信息已经暴露了。
永久登录需要一个永久登录cookie,通常叫做验证cookie,这是由于cookie是被用来在多个会话间提供稳定数据的唯一标准机制。如果该cookie提供永久访问,它就会造成对你的应用的安全的严重风险,所以你需要确定你保存在cookie中的数据只能在有限的时间段内用于身份验证。
第一步是设计一个方法来减轻被捕获的永久登录cookie造成的风险。尽管cookie被捕获是你需要避免的,但有一个深度防范流程是最好的,特别是因为这种机制即使是在一切运行正常的情况下,也会降低验证表单的安全性。这样,该cookie就不能基于任何提供永久登录的信息来产生,如用户密码。
为避免使用用户的密码,可以建立一个只供一次验证有效的标识:
1
|
<?php
|
2
|
3
|
$token = md5(uniqid(rand(), TRUE));
|
4
|
5
|
?>
|
你可以把它保存在用户的会话中以把它与特定的用户相关联,但这并不能帮助你在多个会话间保持登录,这是一个大前提。因此,你必须使用一个不同的方法把这个标识与特定的用户关联起来。
由于用户名与密码相比要不敏感一些,你可以把它存在cookie中,这可以帮助验证程序确认提供的是哪个用户的标识。可是,一个更好的方法是使用一个不易猜测与发现的第二身份标识。考虑在保存用户名和密码的数据表中加入三个字段:第二身份标识(identifier),永久登录标识(token),以及一个永久登录超时时间(timeout)。
01
|
mysql> DESCRIBE users;
|
02
|
+------------+------------------+------+-----+---------+-------+
|
03
|
| Field | Type | Null | Key | Default | Extra |
|
04
|
+------------+------------------+------+-----+---------+-------+
|
05
|
| username | varchar(25) | | PRI | | |
|
06
|
| password | varchar(32) | YES | | NULL | |
|
07
|
| identifier | varchar(32) | YES | MUL | NULL | |
|
08
|
| token | varchar(32) | YES | | NULL | |
|
09
|
| timeout | int(10) unsigned | YES | | NULL | |
|
10
|
+------------+------------------+------+-----+---------+-------+
|
通过产生并保存一个第二身份标识与永久登录标识,你就可以建立一个不包含任何用户验证信息的cookie。
01
|
<?php
|
02
|
03
|
$salt = 'SHIFLETT' ;
|
04
|
05
|
$identifier = md5( $salt . md5( $username . $salt ));
|
06
|
$token = md5(uniqid(rand(), TRUE));
|
07
|
$timeout = time() + 60 * 60 * 24 * 7;
|
08
|
09
|
setcookie( 'auth' , "$identifier:$token" , $timeout );
|
10
|
11
|
?>
|
当一个用户使用了一个永久登录cookie的情况下,你可以通过是否符合几个标准来检查:
01
|
<?php
|
02
|
03
|
/* mysql_connect() */
|
04
|
/* mysql_select_db() */
|
05
|
06
|
$clean = array ();
|
07
|
$mysql = array ();
|
08
|
09
|
$now = time();
|
10
|
$salt = 'SHIFLETT' ;
|
11
|
12
|
list( $identifier , $token ) = explode ( ':' , $_COOKIE [ 'auth' ]);
|
13
|
14
|
if (ctype_alnum( $identifier ) && ctype_alnum( $token ))
|
15
|
{
|
16
|
$clean [ 'identifier' ] = $identifier ;
|
17
|
$clean [ 'token' ] = $token ;
|
18
|
}
|
19
|
else
|
20
|
{
|
21
|
/* ... */
|
22
|
}
|
23
|
24
|
$mysql [ 'identifier' ] = mysql_real_escape_string( $clean [ 'identifier' ]);
|
25
|
26
|
$sql = "SELECT username, token, timeout
|
27
|
FROM users
|
28
|
WHERE identifier = '{$mysql[' identifier ']}' ";
|
29
|
30
|
if ( $result = mysql_query( $sql ))
|
31
|
{
|
32
|
if (mysql_num_rows( $result ))
|
33
|
{
|
34
|
$record = mysql_fetch_assoc( $result );
|
35
|
36
|
if ( $clean [ 'token' ] != $record [ 'token' ])
|
37
|
{
|
38
|
/* Failed Login (wrong token) */
|
39
|
}
|
40
|
elseif ( $now > $record [ 'timeout' ])
|
41
|
{
|
42
|
/* Failed Login (timeout) */
|
43
|
}
|
44
|
elseif ( $clean [ 'identifier' ] !=
|
45
|
md5( $salt . md5( $record [ 'username' ] . $salt )))
|
46
|
{
|
47
|
/* Failed Login (invalid identifier) */
|
48
|
}
|
49
|
else
|
50
|
{
|
51
|
/* Successful Login */
|
52
|
}
|
53
|
54
|
}
|
55
|
else
|
56
|
{
|
57
|
/* Failed Login (invalid identifier) */
|
58
|
}
|
59
|
}
|
60
|
else
|
61
|
{
|
62
|
/* Error */
|
63
|
}
|
64
|
65
|
?>
|
你应该坚持从三个方面来限制永久登录cookie的使用。
- Cookie需在一周内(或更少)过期
- Cookie最好只能用于一次验证(在一次成功验证后即删除或重新生成)
- 在服务器端限定cookie在一周(或更少)时间内过期
如果你想要用户无限制的被记住,那只要是该用户的访问你的应用的频度比过期时间更大的话,简单地在每次验证后重新生成标识并设定一个新的cookie即可。
另一个有用的原则是在用户执行敏感操作前需要用户提供密码。你只能让永久登录用户访问你的应用中不是特别敏感的功能。在执行一些敏感操作前让用户手工进行验证是不可替代的步骤。
最后,你需要确认登出系统的用户是确实登出了,这包括删除永久登录cookie:
1
|
<?php
|
2
|
3
|
setcookie( 'auth' , 'DELETED!' , time());
|
4
|
5
|
?>
|
上例中,cookie被无用的值填充并设为立即过期。这样,即使是由于一个用户的时钟不准而导致cookie保持有效的话,也能保证他有效地退出。
http://www.nowamagic.net/librarys/veda/detail/2076 :出处
PHP安全编程:记住登录状态的安全做法相关推荐
- Outlook邮箱网页版无法记住登录状态
问题起因及描述 Win10笔记本,手贱清了下Chrome的cookie和缓存.结果发现之后每次登录outlook邮箱网页版(实际是学校的邮箱,outlook.office.com或outlook.of ...
- java如何记住登录状态_Spring security实现记住我下次自动登录功能过程详解
一.原理分析 第一次登陆时,如果用户勾选了readme选项,登陆成功后springsecurity会生成一个cookie返回给浏览器端,浏览器下次访问时如果携带了这个cookie,springsecu ...
- php 小程序登录授权解密,微信小程序授权登录,PHP解密数据,并返回用户信息token记住登录状态...
首先创建一个项目,把这些代码都清空,我们自己写! 首先index.wxml,写一个button用于发起登录 index.wxml 点击授权 然后写index.js 通过wx.login()来获取cod ...
- android记录登录状态
android 开发过程中,我们经常有需要记住登陆的状态的情况.下面是我实现这一功能的一些思路 首先假设,咱们已经实现了登录. 要实现记住登录,我们当然需要将一些数据保存到什么地方.android为我 ...
- html 存储登录状态,Vue中保存用户登录状态实例代码
首先我们假设,这里的登录组件(register.vue)是App.vue组件的子组件,是通过路由进入登录组件的. 登录组件中用户点击登录后,后台会传过来一个用户名,我的App.vue组件中需要拿到这个 ...
- 使用session保持登录状态,cookie保存用户账号密码
session保存登录状态与cookie保存账号密码 1. session维持登录状态 1.1 代码实现 2. cookie保存账号密码 2.1 什么是cookie 2.2 cookie记住账号密码 ...
- Android默认记住登录用户名,【教程】Android 记住密码和自动登录界面的实现
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 登录界面源码: LoginActivity.java public class LoginActivity extends Activity { priv ...
- android 状态模式,Android编程设计模式之状态模式详解
本文实例讲述了Android编程设计模式之状态模式.分享给大家供大家参考,具体如下: 一.介绍 状态模式中的行为是由状态来决定的,不同的状态下有不同的行为.状态模式和策略模式的结构几乎完全一样,但它们 ...
- php怎么判断账号已登录,PHP判断用户登录状态
1,浏览器URL访问页面资源, 2,查看SESSION会话是否记录登陆状态,如"否"从3继续,如"是"则到5 3,获取浏览器客户端的COOKIE用户标识信息,如 ...
最新文章
- 物流系统高可用架构案例
- 吴恩达机器学习笔记:(三)梯度下降法
- activiti api文档_【白银人机】Activiti 工作流从入门到入土:完整 hello world 大比拼(API 结合实例讲解)...
- PKU 学生的反馈 2009 –2
- Webstorm设置开发模板
- html5坦克游戏ppt说明,HTML5制作的坦克游戏
- windows server2003的邮箱服务器安装详细步骤
- matlab 包落,怎样在MATLAB中划出一个函数的包络线?
- 在线随机抛硬币正反面统计工具
- linux下安装虚拟天文馆,【地理软件】虚拟天文馆——stellarium
- Jenkins的分布式构建及部署(master~slaver)
- db2的SQL1005N 在本地数据库目录或系统数据库目录中已经存在数据库别名
- GitHub疯传,这个Leetcode刷题手册到底有多流弊?
- 远程医疗中使用AR眼镜,内窥镜,视频远程诊疗方案
- 电力电子技术总结-电力电子器件2
- 经验分享:Flutter尽然还能有这种操作!赶紧收藏备战金三银四!
- bzoj 3157: 国王奇遇记3516: 国王奇遇记加强版
- win10环境安装tensorflow-gpu,软件版本、硬件支持、安装过程
- linux运行QQ,微信,企业微信 (非deepin)
- 【机械臂算法】机械臂动力学参数辨识仿真