什么是JWT
Json Web Token(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519),该Token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其他业务逻辑所必须的声明信息,该Token也可以直接被用于认证,也可被加密。
JWT结构
- 头部(header):包含了两部分,采用的签名算法和token类型
{ "alg": "HS256", "typ": "JWT" }
- 载荷(payload):存放有效信息的地方。有效信息包含三部分
{ "iss": "lion1ou JWT", "iat": 1441593502, "exp": 1441594722, "aud": "www.example.com", "sub": "example@163.com" }
- 标准中注册的声明(建议但不强制使用)
- iss:jwt签发者
- sub:jwt所面向的用户
- aud:接收jwt的一方
- exp:jwt的过期时间,这个过期时间必须要大于签发时间
- nbf:定义在什么时间之前,该jwt都是不可用的
- iat:jwt的签发时间
- jti:jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
- 公共的声明:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密
- 私有的声明:私有声明式提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息
- 标准中注册的声明(建议但不强制使用)
- 签名(signature):header和payload内容转化base64编码后使用 "." 字符串拼接后再用SH256签名算法(header中alg指明的算法)加密,在加密的过程中还需加上secret(密钥),最后得到签名。
注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret,那就意味着客户端是可以自我签发jwt了。
JWT工作流程
- 客户端通过web表单将登陆用户名、密码发送至服务端,这一过程一般是post请求,建议的方式是通过ssl加密传输(https协议),从而避免敏感信息被嗅探
- 服务端验证用户名、密码成功后,将用户的id等其他信息作为jwt payload,将其与header分别进行base64编码拼接后签名,形成一个jwt,并设置有效时间
- 服务端将jwt字符串作为登录成功的返回结果返回给客户端
- 客户端将返回的jwt以cookie的形式保存在浏览器上,并设置cookie的有效时间(建议客户端cookie和服务端jwt的有效时间设置一致),用户登出时需删除客户端cookie
- 客户端在每次请求时将jwt放入http header中的authorization位置(解决XSS和XSRF问题)
- 服务端接收到jwt进行解密和校验,如检查签名是否正确、token是否过期、token的接收方是否是自己等
- 验证通过后服务端使用jwt中包含的用户信息进行其他逻辑操作,返回响应结果,否则返回401
JWT优缺点
- 优点
- jwt数据存放在客户端,不依赖于服务端,可以减轻服务端的压力
- 效率比传统的token验证还要高
- 缺点
- jwt一旦生成之后就无法修改、销毁