(1)Session
客户端发送一个登录请求,服务器验证登录数据无误,会生成一个sessionID,此ID对应的值即登录状态为已登录。服务器有一个key-value映射表,会把这个ID和登录状态存到此表中。
服务器返回的响应头的set-Cookie,会使得客户端收到后自动把sessionID保存到cookie中,登录以后的每次请求的请求头都会自动带上这个cookie。
缺点:
A 服务器存储了 Session,就是做了负载均衡后,假如一段时间内 A 的访问量激增,会转发到 B 进行访问,但是 B 服务器并没有存储 A 的 Session,会导致 Session 的失效。所以每个服务器的状态表必须同步,或者抽离出来统一管理,如使用Redis等服务。
浏览器禁用cookie后只能采用其他方案发SessionID(如URL重写)。
XSS攻击:跨站脚本攻击。坏蛋在某网站的可编辑部分注入脚本,脚本发送信息到坏蛋的服务器后台,坏蛋收集到网站的用户信息/cookie。
CSRF攻击:跨域攻击。
(2)Token
客户端发送一个登录请求,服务器验证登录数据无误,会根据登录数据生成一个Token发送给客户端,服务器不再需要维护状态表。
登陆以后的每次请求都带上这个Token,服务器再解密验证是否合法即可。由于是加密的数据,即使用户可以修改,命中几率也很小。客户端不再使用cookie存储,也有效避免了CSRF攻击。
Token的结构:头部,负载和签名。
头部存储Token的类型和签名算法(如:类型是JWT,加密算法是HS256)
{
"alg": "HS256",
"typ": "JWT"
}
Json 块被 Base64Url 编码形成 JWT 的第一部分。
负载是Token要存储的信息(如:用户姓名和昵称信息)
{
"name": "John Doe",
"alias": "john"
}
Json 块被Base64Url 编码形成 JWT 的第二部分。
签名是由指定的算法,将转义后的头部和负载,加上密钥一同加密得到的。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在此过程中没有更改,并且对于使用私钥进行签名的令牌,它还可以验证 JWT 的发送者的真实身份。