【1】JWT是什么
JWT (全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
简单点说就是一种认证机制),让后台知道该请求是来自于受信的客户端。其是目前最流行的跨域身份验证解决方案,常见流程如下:
客户端使用用户名跟密码请求登录,服务端收到请求去验证用户名与密码;
服务端验证成功,会签发一个Token保存到(Session,redis,mysql…)中,然后再把这个 Token 发送给客户端;
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里;
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token,通常是在header中携带;
服务端收到请求,验证客户端请求里面带着的 Token。
token和jwt什么区别
Token是一种用于身份验证和授权的一般术语,指代一种表示用户身份或权限的凭证。Token可以是任何形式的字符串,例如一次性验证码、访问令牌、刷新令牌等。它们通常被用于客户端与服务器之间的身份验证和授权过程。
JWT是一种具体的令牌实现标准,它是一种基于JSON的开放标准(RFC 7519),用于在不同实体之间安全地传输信息。JWT通常由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。头部包含令牌的类型和加密算法等元数据信息,载荷包含自定义的声明信息,如用户ID、角色等,签名用于验证令牌的完整性和真实性。
【2】JWT的组成
JWT包含三个部分: Header头部,Payload负载和Signature签名。由三部分生成JwtToken,三部分之间用“.”
号做分割。
① Header
JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。
{ "alg": "HS256", "typ": "JWT" }
在上面中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256)。typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。
② 有效载荷(payload)
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。
- iss:发行人
- exp:到期时间
- sub:主题
- aud:用户
- nbf:在此之前不可用
- iat:发布时间
- jti:JWT ID用于标识该JWT
除以上默认字段外,我们还可以自定义私有字段,如下例:
{ "sub": "123456", "name": "jane" }
请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。
JSON对象也使用Base64 URL算法转换为字符串保存。
③ 签名哈希
签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(claims), secret)
在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."
分隔,就构成整个JWT对象。
Base64URL算法
如前所述,JWT头和有效载荷序列化的算法都用到了Base64URL。该算法和常见Base64算法类似,稍有差别。
作为令牌的JWT可以放在URL中(例如api.example/?token=xxx)。 Base64中用的三个字符是"+","/"和"=",由于在URL中有特殊含义,因此Base64URL中对他们做了替换:"="去掉,"+"用"-"替换,"/"用"_"替换,这就是Base64URL算法。
【3】应用实践
引入Maven依赖:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> </dependency>
TokenManager 实例如下:
public class TokenManager { //token有效时长 private long tokenEcpiration = 24*60*60*1000; //编码秘钥 private String tokenSignKey = "123456"; //1 使用jwt根据用户名生成token public String createToken(String username) { String token = Jwts.builder().setSubject(username) .setExpiration(new Date(System.currentTimeMillis()+tokenEcpiration)) .signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact(); return token; } //2 根据token字符串得到用户信息 public String getUserInfoFromToken(String token) { String userinfo = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getSubject(); return userinfo; } //3 删除token public void removeToken(String token) { } }