JSON WEB TOKEN - 告别session和cookie - java demo

JWT简介

JWT认证流程:

  1. 用户登录成功,生成token,返回一个对象(包含token,用户名)
  2. 每次请求都带上这个对象(通过js存储在电脑)
  3. jwt过滤器会校验token解密之后的name是否和用户名相同,相同则放行
  4. 完成(后续可能需要加上token刷新的动作)

详细介绍:JWT 丨 JSON Web Tokens 丨 java-jwt | 详细介绍以及用法

maven依赖

<dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.2.0</version>
</dependency>

JWT生成与解密

package com.hisen.jars.jwt;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.joda.time.DateTime;

/**
 * 利用java-jwt 3.2.0版本
 * 每个版本的方法不大一样
 * Created by hisenyuan on 2017/8/17 at 15:41.
 */
public class Jwt {
  private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545df>?N<:{LWPW_hisen";
  private static final String EXP = "exp";
  private static final String PAYLOAD = "payload";

    /**
   * 生成Token:jwt
   * @param object 传入的加密对象 - 放入PAYLOAD
   * @param maxAge 过期事件,单位毫秒
   * @param <T>
   * @return
   */
  public static <T> String sign(T object, long maxAge) {
    Map<String, Object> map = new HashMap<String, Object>();
    String jsonString = JSON.toJSONString(object);
    map.put("alg", "HS256");
    map.put("typ", "JWT");
    long exp = System.currentTimeMillis() + maxAge;
    System.out.println("JWTUtil 当前时间:"+new DateTime().toString("yyyy-MM-dd HH:mm:ss EE"));
    System.out.println("JWTUtil 过期时间:"+new DateTime(exp).toString("yyyy-MM-dd HH:mm:ss EE"));
    String token = null;
    try {
      token = JWT.create()
          .withHeader(map)//header
          .withClaim(PAYLOAD, jsonString)//存放的内容 json
          .withClaim(EXP, new DateTime(exp).toDate())//超时时间
          .sign(Algorithm.HMAC256(SECRET));//密钥
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return token;
  }

  /**
   * 解密token
   * @param token jwt类型的token
   * @param classT 加密时的类型
   * @param <T>
   * @return 返回解密后的对象 - 如果token过期返回空对象
   */
  public static <T> T unsign(String token, Class<T> classT)  {
    DecodedJWT decode = JWT.decode(token);
    Map<String, Claim> claims = decode.getClaims();
    if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)){
      long tokenTime = claims.get(EXP).asDate().getTime();
      long nowTime = new Date().getTime();
      // 判断令牌是否超时
      if (tokenTime > nowTime){
        String json = claims.get(PAYLOAD).asString();
        return JSON.parseObject(json, classT);
      }
    }
    return null;
  }
}

解密的另外一种写法

这种写法如果令牌超时,直接运行时异常,无法做相关处理

  /**
   * 解密token
   * @param token jwt类型的token
   * @param classT 加密时的类型
   * @param <T>
   * @return 返回解密后的对象 - 如果token过期返回空对象
   */
  public static <T> T unsign(String token, Class<T> classT)  {
    JWTVerifier verifier = null;
    try {
      verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
      DecodedJWT jwt = verifier.verify(token); // 如果超时,直接抛出运行时异常
      Map<String, Claim> claims = jwt.getClaims();
      if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
        long tokenTime = claims.get(EXP).asDate().getTime();
        long now = new Date().getTime();
        // 判断令牌是否已经超时
        if (tokenTime > now) {
          String json = claims.get(PAYLOAD).asString();
          // 把json转回对象,返回
          return JSON.parseObject(json, classT);
        }
      }
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    } catch (TokenExpiredException e){
      e.printStackTrace();
    }
    return null;
  }
posted @ 2017-08-27 20:32  间隔  阅读(2258)  评论(0编辑  收藏  举报