登录态维护的方式
JWT(json web token)
JWT是一种开放的json格式token存储标准,通过签名来校验token的合法性,用JWT保存登录信息,优点在于服务端无需维护登录态,不需要将登录状态保存在第三方存储中,所以JWT是无状态的。但缺点也是由此产生的,token仅在客户端维护,所以无法在服务端清除登录状态。
特点:
- JWT默认是不加密的,但可以把token加密一次再放到JWT里;
- JWT不仅可以用于认证,也可以做信息交换,可以降低服务端查数据库的频次;
- JWT本身包含token,如果泄漏了,任何人都可以获得该token拥有的权限,所以为了防止盗用,JWT的有效期应该设置比较短,而且应该用https加密传输,如果访问的权限级别比较高,最好再进行二次认证。
数据组成
JWT由三部分组成,${header}.${payload}.${signature}
;
header
头部是一个JSON对象,描述JWT的元数据;
1
2
3
4
{
"alg": "HS256", // 签名算法,默认是HMAC SHA256,简写成HS256
"typ": "JWT" // 表示token的类型,JWT默认就是JWT
}
payload
负载部分也是一个JSON对象,用来存放实际需要传递的数据,JWT规定了7个官方字段,还可以自定义其他的。
1
2
3
4
5
6
7
8
9
10
11
12
13
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
值得注意的是,JWT默认是不加密的,所以不应该把重要信息放在这个部分,另外这个JSON对象需要使用base64url
算法转换成字符串。
signature
签名是对前两部分的签名,为了防止数据被篡改。具体签名过程,需要服务端生成一个密钥(secret
),作为加签算法的密钥,通过header
中指定的加签算法,按照下面的公式产生签名。当服务端收到JWT后,会对比签名这个字段,来确定token是否被篡改。
1
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
Base64Url:这个算法跟 Base64 算法基本类似,但有一些小的不同。JWT 作为一个令牌,有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法。
session和cookie
cookie
cookie是保存在浏览器的一小块数据,通常会在浏览器发送请求时,携带在请求头部;
有两种类型,一种是session cookie
不包含到期日期,存储在内存中,浏览器关闭cookie就删除了;另一种是persistent cookie
包含到期日期,是存储在磁盘中的,到期后就删除。
session
Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
常见误区:Session 不是关闭浏览器就消失了。对 Session 来说,除非程序通知服务器删除一个 Session,否则服务器会在Session失效前一直保留。大多数情况下浏览器是不会在关闭网页之前通知服务器的,所以服务器根本不知道浏览器已经关闭。
之所以会有这种错觉,是大部分 session 机制都使用会话 cookie 来保存 session id,而关闭浏览器后这个 session id 就消失了,再次连接服务器时也就无法找到原来的 session。如果服务器设置的 cookie 被保存在硬盘上,或者使用某种手段改写浏览器发出的 HTTP 请求头,把原来的 session id 发送给服务器,则再次打开浏览器仍然能够打开原来的 session。
区别
安全性: 由于Session 是存储在服务器端的,Cookie 是存储在客户端的,所以Cookie被盗用的可能性相较于Session会更高一些。 存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。 存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。