我们知道,http协议是无状态的,所以每次访问服务器的时候,都需要告诉服务器访问者的身份。在以前,我们常用Cookie+Session来完成服务器端验证。
具体过程为在客户端提交表单登录,服务器端通过验证之后,生成一个Session对象,存放用户登录信息,并将SessionID存放到Cookie中,通过Http响应发送到客户端。而客户端会在一定时间内保存cookie,此后的访问请求都会在请求头中带上Cookie的值,用于让服务器端验证,从而达到一次登录,后续不用验证的目的。
Session的缺点:
先来看看token的介绍:
Json Web Token:简称JWT,俗称token,它是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于网络应用环境间传递声明而执行的一种基于JSON的开放标准。JWT传递的信息可以被验证和信任,因为它是数字签名的。JWTs可以使用一个秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对来签名。
JWT 的三个部分依次如下:
Header(头部) Payload(负载) Signature(签名),写成一行,就是下面的样子。
Header.Payload.Signature
下面依次介绍这三个部分。
1. Header 头部
Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。
{ "alg": "HS256", "typ": "JWT" }
上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。
最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串。
2. Payload 有效载荷
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。
{ "sub": "1234567890", "name": "sssssss", "admin": true }
注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
这个 JSON 对象也要使用 Base64URL 算法转成字符串。
3. Signature 签名
jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
header (base64后的)
payload (base64后的)
secret(这个是服务器端自定义的一个秘钥)
这个部分需要base64加密后的header和base64加密后的payload使用连接组成的字符串,以及秘钥secret构成一个组合,然后通过header中声明的加密方式对这个组合进行加密,然后就构成了jwt的第三部分。
最后我们会得到完整的JWT:字符串1.字符串2.字符串3;
再来看看token是怎么做的:
1、客户端通过用户名和密码登录服务器
2、服务端对客户端身份进行验证;
3、服务端对该用户生成Token,返回给客户端;
4、客户端将Token保存到本地浏览器,一般保存到cookie中;
5、客户端发起请求,需要携带该Token;
6、服务端收到请求后,首先验证Token,之后返回数据。
服务端不需要保存Token,只需要对Token中携带的信息进行验证即可。无论客户端访问后台的那台服务器,只要可以通过用户信息的验证即可。
本人碰到的常用做法是用户登录验证通过后,将用户的uuid保存在JWT的有效载荷中并返回,之后的请求只要通过解析token获得用户的uuid,就可以对用户进行之后的操作。
防干扰:生成token的过程中,ua的充作干扰码。没有相同的ua,就无法解析生成的token字符串。如果客户端是混合开发的模式,生成token和使用token的代理可能不同(比如一个是h5,一个是原生),ua就会不同,token就无法成功的使用。
防过期(刷新):Token管理者负责根据用户的数据生成token和摘要,摘要用来给APP端刷新token用