名词介绍
cookie:浏览器访问服务器,服务器返回cookie给浏览器,浏览器在本地存储cookie,下次带着cookie访问服务器,服务器返回相应的数据。
session:浏览器访问服务器,服务器会存储浏览器的数据value,并把key返回给浏览器,浏览器下次带着key(session ID)来访问服务器,服务器能根据key来获取数据。如果有负载均衡,则是session的一个痛点 。
token:浏览器访问服务器,服务器保留一份密钥并返回一个加密之后的token给浏览器,浏览器拿着token访问服务器,服务器根据密钥验证token,然后返回数据。
三者区别
session和token的区别:
1、数据存放位置不同:session数据是存放在服务器中的,cookie是存放在浏览器中的。
2、用户安全程度不同:cookie数据存放在浏览器本地不是很安全,session存放在服务器中相对安全。
3、性能使用程度不同:session数据放在服务器上,访问增多会占用服务器的性能,如果考虑到减轻服务器性能方面,应该使用cookie。
4、数据存储大小不同:单个cookie保存的数据不能超过4k,session存储在服务器,根据服务器大小来定。
token和session的区别:
1、token是开发定义的,session是http协议规定的
2、token不一定存储在服务器中,session存储在服务器中
3、token可以跨域,session不可用跨域,它是与域名绑定的
如何解决cookie安全性问题
1、cookie有效期不要设置太长。
2、设置HttpOnly属性为true,可以防止js脚本读取cookie信息,防止XSS攻击。
3、设置复杂的cookie,加密cookie。cookie的key使用uuid随机生成,value可以使用复杂组合,比如:用户名+当前时间+cookie有效期+随机数。这样可以尽可能使加密后的cookie更难解密,从而保护了cookie中的信息。
4、用户第一次登录时,服务器保存IP+cookie加密后的token。后面每次请求,都去将当前cookie和IP组合起来加密后的token与保存的token作对比,只有完全对应才能验证成功。
5、如果网站支持https,尽可能使用https。如果网站支持https,那么可以为cookie设置Secure属性为true,表示cookie只能使用https协议发送给服务器。
理解jwt
JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用.
进行连接形成最终传输的字符串。
1.Header
JWT头是一个描述JWT元数据的JSON对象,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存
{
"alg": "HS256",
"typ": "JWT"
}
2.Payload
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
这些预定义的字段并不要求强制使用。除以上默认字段外,我们还可以自定义私有字段,一般会把包含用户信息的数据放到payload中,如下例:
{
"sub": "1234567890",
"name": "Helen",
"admin": true
}
请注意,默认情况下JWT是未加密的,因为只是采用base64算法,拿到JWT字符串后可以转换回原本的JSON数据,任何人都可以解读其内容,因此不要构建隐私信息字段,比如用户的密码一定不能保存到JWT中,以防止信息泄露。JWT只是适合在网络中传输一些非敏感的信息
3.Signature
签名哈希部分是对上面两部分数据签名,需要使用base64编码后的header和payload数据,通过指定的算法生成哈希,以确保数据不会被篡改。首先,需要指定一个密钥(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用header中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名
HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用.
分隔,就构成整个JWT对象
注意JWT每部分的作用,在服务端接收到客户端发送过来的JWT token之后:
- header和payload可以直接利用base64解码出原文,从header中获取哈希签名的算法,从payload中获取有效数据
- signature由于使用了不可逆的加密算法,无法解码出原文,它的作用是校验token有没有被篡改。服务端获取header中的加密算法之后,利用该算法加上secretKey对header、payload进行加密,比对加密后的数据和客户端发送过来的是否一致。注意secretKey只能保存在服务端,而且对于不同的加密算法其含义有所不同,一般对于MD5类型的摘要加密算法,secretKey实际上代表的是盐值