Java: JWT

 

 测试JWT

package com.example.jwt;


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.jwt.util.JWTUtil;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.HashMap;

public class TestJwt{
  @Test
  void generate() throws InterruptedException{
    HashMap<String, Object> hashMap = new HashMap<>();

    LocalDateTime localDateTime = LocalDateTime.now().plusSeconds(3);
    System.out.println("localDateTime = " + localDateTime);
    String sign = JWT.create()
      .withHeader(hashMap)  // 可省略
      .withClaim("id", 55)
      .withClaim("name", "proofread")
      .withExpiresAt(Date.from(localDateTime.toInstant(ZoneOffset.ofHours(8)))).sign(Algorithm.HMAC256("ruzz"));
    System.out.println("\033[37;7m" + sign + "\033[0m");

    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("ruzz")).build();

    System.out.println("\033[37;7m" + sign + "\033[0m");
    DecodedJWT decodedJWT = jwtVerifier.verify(sign);
    Claim id = decodedJWT.getClaim("id");
    System.out.println("\033[37;7m" + id.asInt() + "\033[0m");
    Claim name = decodedJWT.getClaim("name");
    System.out.println("\033[37;7m" + name.asString() + "\033[0m");
    Date expiresAt = decodedJWT.getExpiresAt();
    System.out.println("expiresAt = " + expiresAt);

    Thread.sleep(3500);

    try{
      DecodedJWT decodedJWT1 = jwtVerifier.verify(sign);
    }catch(JWTVerificationException e){
      throw new RuntimeException(e);
    }
  }

}

 

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


Springboot整合:

application.yaml
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: coalesce
  mvc:
    servlet:
      path: /servlet
# Mybatis
mybatis:
  mapper-locations: classpath:mapper/*.xml  # mapper配置文件位置
  type-aliases-package: com.example.jwt.entity  # 实体类包名, 默认别名: 类名首字母小写
# Logging
logging:
  charset:
    console: UTF-8
    file: UTF-8
  level:
    root: info  # 全局
    org.springframework: info  # 第三方
    com.example.jwt: info
    com.example.jwt.dao: debug
    sql: debug
    web: debug
server:
  servlet:
    context-path: /ctx

 


UserDAO.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.jwt.dao.UserDAO">
  <select id="login" parameterType="User" resultType="User">
    SELECT * FROM users WHERE name = #{name} AND password = #{password}
  </select>
</mapper>

 

DAO层:

package com.example.jwt.dao;


import com.example.jwt.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserDAO{
  User login(User user);
}

实体类

package com.example.jwt.entity;


import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class User{
  private Integer id;
  private String name;
  private String password;
}

 

启动类

package com.example.jwt;


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(value = {"com.example.jwt.dao"})
public class JwtApplication{

  public static void main(String[] args){
    SpringApplication.run(JwtApplication.class, args);
  }

}

 

工具类

package com.example.jwt.util;


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Map;

public class JWTUtil{
  private static final String secret = "compound";
  private static final Algorithm ALGORITHM = Algorithm.HMAC384(secret);

  public static String getToken(Map<String, String> map){
    // 默认7天过期
    ZonedDateTime zonedDateTime = LocalDateTime.now().plusDays(7).atZone(ZoneId.systemDefault());
    Date expireDate = Date.from(zonedDateTime.toInstant());
    JWTCreator.Builder builder = JWT.create();
    map.forEach(builder::withClaim);  // 构建payload

    return builder.withExpiresAt(expireDate).sign(ALGORITHM);
  }

  public static DecodedJWT verifyToken(String token){
    return JWT.require(ALGORITHM).build().verify(token);
  }
}

 

Service层:

UserService.java

package com.example.jwt.service;


import com.example.jwt.entity.User;

public interface UserService{
  User login(User user);
}

 

UserServiceImpl.java

package com.example.jwt.service;


import com.example.jwt.dao.UserDAO;
import com.example.jwt.entity.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class UserServiceImpl implements UserService{
  private final UserDAO userDAO;

  public UserServiceImpl(UserDAO userDAO){
    this.userDAO = userDAO;
  }

  @Override
  public User login(User user){
    User userFromDB = userDAO.login(user);
    if(userFromDB != null)
      return userFromDB;
    throw new RuntimeException("login failed");
  }
}

 

Controller

package com.example.jwt.controller;


import com.example.jwt.entity.User;
import com.example.jwt.service.UserService;
import com.example.jwt.util.JWTUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping(value = "user")
public class UserController{
  private final UserService userService;

  @Autowired
  public UserController(UserService userService){
    this.userService = userService;
  }


  @RequestMapping(value = "login")
  public Map<String, Object> login(User user){
    System.out.println("\033[37;7m" + user + "\033[0m");
    HashMap<String, Object> hashMap = new HashMap<>();
    try{
      User userFromDB = userService.login(user);
      HashMap<String, String> payload = new HashMap<>();
      payload.put("id", String.valueOf(userFromDB.getId()));
      payload.put("name", userFromDB.getName());
      payload.put("password", userFromDB.getPassword());

      String token = JWTUtil.getToken(payload);

      JWTUtil.getToken(payload);
      hashMap.put("state", true);
      hashMap.put("msg", "success");
      hashMap.put("token", token);
    }catch(Exception e){
      hashMap.put("state", false);
      hashMap.put("msg", e.getMessage());
    }
    return hashMap;
  }

  @PostMapping(value = "test")
  public Map<String, Object> test(String token){
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("state", true);
    hashMap.put("msg", "success");
    return hashMap;
  }
}

 

HandlerInterceptor

package com.example.jwt.interceptor;


import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.example.jwt.util.JWTUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

public class JWTInterceptor implements HandlerInterceptor{
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
    HashMap<String, Object> hashMap = new HashMap<>();
    String token = request.getHeader("token");
    try{
      JWTUtil.verifyToken(token);
      return true;
    }catch(SignatureVerificationException e){
      e.printStackTrace();
      hashMap.put("msg", "Signature has been modified");  // secret几乎不可能出错
    }catch(TokenExpiredException e){
      e.printStackTrace();
      hashMap.put("msg", "Token has expired");
    }catch(AlgorithmMismatchException e){
      e.printStackTrace();
      hashMap.put("msg", "Algorithm mismatched");
    }catch(JWTDecodeException e){
      e.printStackTrace();
      hashMap.put("msg", "Token format invalid");
    }catch(Exception e){
      e.printStackTrace();
      hashMap.put("msg", "Invalid token");
    }
    hashMap.put("state", false);
    String json = new ObjectMapper().writeValueAsString(hashMap);
    response.setContentType("application/json; charset=UTF-8");
    response.getWriter().println(json);
    return false;
  }
}

 

添加HandlerInterceptor

package com.example.jwt.config;


import com.example.jwt.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// @Component
@Configuration
public class InterceptorConfig implements WebMvcConfigurer{
  @Override
  public void addInterceptors(InterceptorRegistry registry){
    registry.addInterceptor(new JWTInterceptor())
      .addPathPatterns("/user/**")  // 与context-path & servlet.path无关
      .excludePathPatterns("/user/login");
  }
}

 

 

 

 

posted @ 2022-05-02 09:05  ascertain  阅读(108)  评论(0编辑  收藏  举报