JWT是什么?
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。
JWT全称JSON Web Token,是一种传输信息的标准,用于JSON对象在各方之间安全地传输信息。支持JSON对象传输,是JWT比较优越的一点。
为什么要使用JWT?
基于oauth2协议认证过程中,以密码类型认证方式为例,包括认证和授权两个步骤。分别如下:
- 客户端通过客户端用户名和密码,密码授权方式,以及用户名和密码,向授权服务器认证,如果有效则返回。token(访问令牌)。
- 客户端携带token(访问令牌)访问资源服务器,资源服务器验证token,如果有效则返回受保护的资源。
一般在资源服务验证token时,需要通过token向授权服务器调用认证服务,并且,需要通过token向授权服务器获取用户信息。在服务的相互调用过程中,会频繁地调用授权服务器,如果使用JWT有如下几个优势:
- 由于JWT具有时效性,如果token失效则直接校验失败
- 在资源服务可以基于密钥对token进行校验,而无需调用授权服务器的认证服务,避免频繁调用认证服务器。
- 在JWT中携带非敏感的认证信息,同样避免了频繁调用授权服务器获取用户相关信息,方便了在服务之间传递。
并且,JWT还有下面的优点:
- 流行
- 安全
- 稳定
- 易用
- 支持 JSON
所有这些因素,令 JWT 名声大振
JWT比token更方便。由于token的验证需要调用认证服务,并且需要通过token向授权服务器获取用户信息,在这个过程中,会频繁调用授权服务器,而使用JWT可以避免这个缺点,使用JWT可以避免频繁调用认证服务器,同时JWT中携带了非敏感的身份认证信息(不必担心泄露后造成风险),同样可以避免频繁调用授权服务器。
JWT的数据结构
一个典型的JWT如下图所示,他通常由头部(Header)、载荷(Payload)、签名 (Signature)组成。
JWT头部:通常由算法类型和令牌类型两部分组成,使用 Base64Url 编码表示
算法类型:指定用于生成签名的算法,例如 HMAC、RSA 或者 ECDSA。
令牌类型:指定令牌的类型,常见的是 JWT。
如下面的数据,是一个JWT头部:
{"alg": "HS256",none"typ": "JWT"
}
载荷(Payload):也使用 Base64Url 编码表示,载荷存储了有关用户或实体的声明等一些有用信息。
声明:如用户 ID、角色、权限等信息。
注册声明:包含一些标准的声明(比如发行人、过期时间等)和一些自定义的 声明。
标准中注册的声明(建议但不强制使用):
- iss: jwt签发者
- sub:jwt所面向的用户
- aud: 接收jwt的一方
- exp:jwt的过期时间,这个过期时间必须要大于签发时
- nbf: 定义在什么时间之前,该jwt都是不可用的
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
如下面的数据,是一个JWT载荷:
{"sub": "1234567890","name": "John Doe","iat": 1516239022
}
签名(Signature):签名是对头部和载荷进行签名的结果,用于验证 JWT 的完整性和真实性。
签名生成方式:将头部和载荷进行 Base64Url 编码后拼接在一起,然后使 用指定的加密算法(如 HMAC、RSA)进行签名,将生成的签名添加到 JWT 中
JWT的工作过程
如下图,在用户登录账户名和密码时,如果认证成功,服务器会创建一个JWT cookie,将该cookie返回给用户,然后用户带着这个cookie再去访问服务器,服务器检查JWT是否合法,如果合法则返回一个响应: