解决几个疑惑
- HTTP 是一个无连接且无状态协议,客户端每次发出请求时,下一次请求无法得知上一次请求所包含的状态数据,如何能把一个用户的状态数据关联起来呢?
- 如何对用户进行身份验证?
关键字 token、cookie和session 的理解
token 令牌
是验证身份的一种方式。最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。
引申问题
- 攻击者会不会伪造token?
cookie
浏览器里一种能永久保存的数据。由服务器产生,发送给浏览器。
cookie的组成有:名称(key)、值(value)、有效域(domain)、路径(域的路径,一般设置为全局:”\”)、失效时间(expires)、安全标志(指定后,cookie只有在使用SSL连接时才发送到服务器(https))。
expires 和 maxAge:告诉浏览器这个 cookie 什么时候过期,expires 是 UTC 格式时间,maxAge 是 cookie 多久后过期的相对时间。当不设置这两个选项时,会产生 session cookie,session cookie 是 transient 的,当用户关闭浏览器时,就被清除。
- 读取cookie
document.cookie
- 写入cookie
document.cookie = 'name=abigale'
以下是我从某个网站截取下的请求信息,可以看到 cookie
里的信息
例子: expires设置有效时间
|
|
session 会话
当用户去访问某个服务器时,服务器会产生session然后存下用户的信息。session是通过 session_id
去识别用户的。
- session存放位置可以是
- 内存
- cookie本身
- redis 或 memcached 等缓存中
- 数据库中。(线上来说,缓存的方案比较常见,存数据库的话,查询效率相比前三者都太低,不推荐)
传统的身份验证:cookie和session之间的合作
说在cookie和session之前:
为什么会有cookie又有session:
- 原因一:因为如果我们把所有信息全都存在cookie,cookie有很容易被用户在浏览器看到或者在js脚本修改,cookie存储数据大小也受限,太大传输效率就低了,所以我们把一些敏感或者量大的数据存在session里。
- 原因二:将两者信息进行匹配验证,即浏览器(cookie)和服务器端(session)之间的验证。
为什么需要这两者的合作?
- HTTP是一种无状态无连接的协议,即请求是不知道是谁请求,需要在这两者之间做一层身份的识别。就如原本是去商场用现金交易,付款后就不知道用户是谁了,但后来变成线上支付,加了一层身份识别,我们就可以对用户进行追踪了。
合作过程
- 客户端访问时,通过了验证。
- 服务端将客户端信息进行处理加密(签名,专业术语叫信息摘要算法)。
- 把记录这些信息的ID发送给客户端
- 客户端收到ID后存储在cookie中
- 下次客户端重新访问服务端时,带上cookie信息
- 服务端验证cookie里面的信息,如果能找到对应的记录,则用户通过了验证
引申出的问题:
为什么要加密?
比如我们放在浏览器的信息是可以通过js拿到的或者其他攻击拿到的,很不安全。如果我们通过某种信息加密手段,就可以防止攻击者冒充用户去干坏事。
可以怎么加密呢?下面举个例子
- 秘密字符串:如
"thisIsMySecret"
- 本来发送给服务端的cookie:
"name:abigale"
,这时abigale用户可以伪装成另一位同学yuhaha,如cookie:"name:yuhaha"
- 这是服务器做个sha1加密:
sha1("thisIsMySecret","abigale")
,然后把某个加密后的签名(如:4850a42e3bc0ac94323d3923e3d1d)发给用户 后来用户发给服务器端的cookie就变成了
1234{name: 'abigale','user.sig': '4850a42e3bc0ac94323d3923e3d1d'}到这时,如果攻击者将cookie改为
1234{name: 'yuhaha','user.sig': '4850a42e3bc0ac94323d3923e3d1d'}
签名就匹配不上了,要伪造对应的签名几率很小很小
- 这就是完成一个加密过程了。这个过程是用来识别用户,针对了HTTP面向无连接(请求完就断开)的方法。
新的验证机制 – token认证
以上我们讲到我们采用 session_id
去匹配用户验证用户完成一次API请求,但每次请求都要去做匹配。一种新的请求机制是token认证
快速理解:我们将一些需要验证的信息在服务端做一次加密,包括一些失效期等,然后返回给客户端,客户端将token存起来,下次访问再讲token传给服务端验证。