赞
踩
在计算机身份认证中代表令牌,在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。
JWT(JSON Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。
它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证;应用场景如用户登录。
目前主流的Web开发模式有两种:
- 基于服务端渲染的传统Web开发模式
- 基于前后端分离的新型Web开发模式
对于这两种开发模式的身份认证,服务端渲染推荐使用 Session认证机制,前后端分离推荐使用JWT认证机制。
对于传统的session认证,因为HTTP是无协议的,为了记住用户状态,服务器在用户第一次访问时会返回一个cookie同时服务端保存一个对应的session,但是这种基于session的认证使应用本身很难得到扩展,随着不同客户端用户的增加,大量session会话的创建对服务器是一个巨大的开销;
同时,当服务端为集群时,用户登录其中一台服务器,会将session保存在该服务器的内存中,
只有再次访问这台服务器才能拿到授权资源。
另外session认证机制依赖Cookie,但是Cookie默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域Session认证。这就有了JWT的出现,流程上是这样的:
JWT由三部分构成,第一部分我们称它为头部(header),第二部分我们称其为载荷(payload),第三部分是签证(signature)。
{
“typ”: “JWT”,
“alg”: “HS256”
}
由上可知,该token使用HS256加密算法,将头部进行base64加密(该加密是可以对称解密的),构成了第一部分:
eyJhbGciOiJIUzI1NiJ91
Playload:载荷就是存放有效信息的地方,这些有效信息包含三个部分
1、 Registered claims(注册声明): 这些是一组预先定义的声明,它们不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行者),exp(到期时间),sub(主题),aud(受众)等
2、Public claims (公开声明): 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密。
3、Private claims(私有声明): 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
{
“iss”: “Online JWT Builder”,
“iat”: 1416797419,
“exp”: 1448333419,
…….
“userid”:10001
}
有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息。然后将其进行base64加密,得到Jwt的第二部分:
eyJ1c2VyaWQiOjB91
例如头部与载体加密拼接后的字符串为eyJhbGciOiJIUzI1NiJ91.eyJ1c2VyaWQiOjB91再次利用加密算法(HS256)与自定义的密钥(secret)加密得到签名部分字符:
rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
将上面三个方法生成的字符串再次拼接就得到了完整的Token:
eyJhbGciOiJIUzI1NiJ91.eyJ1c2VyaWQiOjB91.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token
优点:
1、因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
2、payload可以在自身存储一些其他业务逻辑所必要的非敏感信息。
3、它不需要在服务端保存会话信息, 所以它易于应用的扩展
缺点:
1、安全性:由于JWT的payload是使用Base64编码的,并没有加密,因此JWT中不能存储敏感数据。而Session的信息是存在服务端的,相对来说更安全。
2、一次性:无状态是JWT的特点,但也导致了这个问题,JWT是一次性的。想修改里面的内容,就必须签发一个新的JWT。即缺陷是一旦下发,服务后台无法拒绝携带该jwt的请求(如踢除用户)
Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位,而Token的playload部分一般会存储相关的过期时间,一旦Token过期就会被拦截,因此如何设置Token刷新机制也是一个重点。
过长的过期时间会让系统有长期暴露在接口的风险,理论上过期时间越短越好,但是过短的时间明显会带来不好的用户体验。那么我们可以考虑使用Refresh Token刷新,一旦 Token 过期,就反馈给前端,前端使用 Refresh Token 申请一个全新 Token 继续使用。
这种方案中,服务端只需要在客户端请求更新 Token 的时候对 Refresh Token 的有效性进行一次检查,大大减少了更新有效期的操作,也就避免了频繁读写。
前端第一次发起请求时,后端准备两个 token,一个有效时间较短的作为认证 token(token),一个有效时间较长的作为刷新 token(refreshToken),返回给前端。
前端拿到两个 token 后,把它们都存储在 localStorage 中,后面再次发起请求时携带两个token:
demo:
Token refresh的实现
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。