1、简介

JWT,JSON Web Token的简写,是目前比较流行的跨域认证解决方案,它不是一个具体的技术实现,而更像是一种标准。
官网:JSON Web Tokens - jwt.io

2、JWT数据结构

JWT由3部分构成:

  • Header(头部)

  • Payload(负载)

  • Signature(签名)

Header
Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子

{
  "alg": "HS256",
  "typ": "JWT"
}

alg
属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);
typ
属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。

最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串。

Payload
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。如:

{
  "id": "123",
  "name": "river"
}

JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

这个 JSON 对象也要使用 Base64URL 算法转成字符串。

Signature
Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用(.)分隔。

JWT是可以被解码的,所以不要在JWT的Payload中存放私密数据。

JWT

3、JWT使用

引入依赖

<dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt</artifactId>
      <version>0.9.0</version>
</dependency>

由于我们需要通过jwt生成token,并能通过token解析生成原始数据,所以可以封装成工具类。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
 
import java.util.*;
 
public class JwtUtils {
 
    private static final String SECRET = "jwt123456";
 
    public static String generateToken(Map<String, Object> claims, Date expireTime) {
        return Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS256, SECRET)
                .setExpiration(expireTime)
                .compact();
    }
 
    public static Map<String, Object> parseToken(String token) {
        try {
            Claims body = Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
            return body;
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
        }
        return null;
    }
}

在我们做登录鉴权的项目时,服务端生成jwt返回给客户端,客户端可以将jwt储存在Cookie里面,也可以储存在 localStorage。此后,客户端每次与服务器通信,都带上这个jwt。放在 Cookie 里面可以自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求头中。

4、使用JWT需要注意的地方

1、JWT 中的数据默认是不加密的,不加密的情况下,不能将秘密数据写入JWT;
2、一旦JWT签发了,在到期之前始终有效,除非服务器有额外的限制逻辑(如使用redis控制登录session有效期),所以需要设置有效期;
3、为防止泄露,JWT不应该使用HTTP协议明码传输,要使用HTTPS协议传输。