JWT

发布时间 2023-03-28 23:27:01作者: 秋夜雨巷

JWT

JSON Web Token(缩写 JWT)是跨域认证解决方案。

为什么用JWT

传统的单体应用,服务器端生成存储session_id发送给客户端,客户端保存在cookie中,客户端后面每次请求通过cookie把session_id 传回服务器,服务器根据session_id对比确认身份。
但如果是服务器集群,或者是跨域的服务导向架构,就要求session数据共享,每台服务器都能够读取session。
一种解决方案是 session 数据持久化,写入数据库或别的持久层(如存入redis)。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。
另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

java代码

pom

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

生成token

//1、准备数据
Map map = new HashMap();
map.put("id",1);
map.put("mobile","110");

//2、使用JWT生成token
long now = System.currentTimeMillis();  //获取当前时间(设置失效时间用)
String token = Jwts.builder()
        .signWith(SignatureAlgorithm.HS512, "autumn") //指定加密算法和key
        .setClaims(map) //写入数据
        .setExpiration(new Date(now + 30000)) //失效时间
        .compact();

解析token

解析时如果过期或者密钥不对都会解析失败抛异常

try {
    Claims claims = Jwts.parser()
            .setSigningKey("autumn")
            .parseClaimsJws(token)
            .getBody();
    Object id = claims.get("id");
    Object mobile = claims.get("mobile");
    System.out.println(id + "--" + mobile);
}catch (ExpiredJwtException e) {
    System.out.println("token已过期");
}catch (SignatureException e) {
    System.out.println("token不合法");
}

工具类

import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {

    // TOKEN的有效期1小时(S)
    private static final int TOKEN_TIME_OUT = 1 * 3600;

    // 加密KEY
    private static final String TOKEN_SECRET = "autumn";


    // 生成Token
    public static String genToken(Map params){
        long currentTime = System.currentTimeMillis();  //获取当前时间(设置失效时间用)
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, TOKEN_SECRET) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳
                .addClaims(params)
                .compact();
    }


    /**
     * 获取Token中的claims信息
     */
    public static Claims getClaims(String token) {

        if (token!=null && !StringUtils.isEmpty(token)) {
            try {
                return Jwts.parser()
                        .setSigningKey(TOKEN_SECRET)
                        .parseClaimsJws(token).getBody();
            }catch (ExpiredJwtException e){
                System.out.println("token已过期");
                return null;
            }catch (UnsupportedJwtException e){
                System.out.println("token不合法");
                return null;
            }catch (Exception e){
                return null;
            }
        }else{
            return null;
        }
    }


    /**
     * 验证token是否有效 true-有效,false-失效
     */
    public static boolean verifyToken(String token) {
        if (token!=null && !StringUtils.isEmpty(token)) {
            try {
                JwtParser jwtParser = Jwts.parser();
                jwtParser.setSigningKey("TOKEN_SECRET");
                //只做token验证,若不通过,则抛异常
                Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
                return true;
            }catch (ExpiredJwtException e){
                System.out.println("token已过期");
                return false;
            }catch (UnsupportedJwtException e){
                System.out.println("token不合法");
                return false;
            }catch (Exception e){
                return false;
            }
        }else{
            return false;
        }
    }

    public static void main(String[] args) {
        //生成token
        //1、准备数据
        Map map = new HashMap();
        map.put("id",1);
        map.put("mobile","110");

        //2、使用JWT生成token
        String token = JwtUtils.genToken(map);
        System.out.println(token);

        //3、使用JWT解析token
        Claims claims = JwtUtils.getClaims(token);

        Object id = claims.get("id");
        Object mobile = claims.get("mobile");
        System.out.println(id + "--" + mobile);
    }
}

image

参考:https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html