JWT:
传统session认证:
概念:

演示:
@RestController
public class Controller {@RequestMapping("test")public Object test(String name, HttpServletRequest req) {req.getSession().setAttribute("name", name);return req.getSession().getAttribute("name");}
}



缺陷:
JWT认证:
认证流程:

优势:
结构:
{"alg": "SHA256","type": "JWT"
}
{"name": "zhangsan""admin": true
}
依赖:
com.auth0 java-jwt 3.19.3
测试类:
public class JwtCreate {@Testpublic void create() {Calendar instance = Calendar.getInstance();instance.add(Calendar.DATE, 3); // 3天Map header = new HashMap<>();header.put("alg", "SHA256");header.put("type", "JWT");String token = JWT.create().withHeader(header) // header.withClaim("uid", "001") // payload.withClaim("name", "zhangsan") // payload.withClaim("admin", true) // payload.withExpiresAt(instance.getTime()) // 指定令牌过期时间(3天后过期).sign(Algorithm.HMAC256("chen1020")); // signatureSystem.out.println(token);}
}
输出:

注意:
.withHeader(header) 一般不写,直接用默认配置测试方法:
@Testpublic void verify() {// 创建验证对象JWTVerifier verifier = JWT.require(Algorithm.HMAC256("chen1020")).build();// 验证tokenDecodedJWT verify = verifier.verify("eyJ0eXAiOiJKV1QiLCJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJ1aWQiOiIwMDEiLCJuYW1lIjoiemhhbmdzYW4iLCJhZG1pbiI6dHJ1ZSwiZXhwIjoxNjY5ODc1MTI3fQ.-eewHSjiqXQggakhJayx2mOfqmRS8iz4Ockb_BKg_0o");// 获取用户信息(验证通过后才能获取)System.out.println(verify.getClaims());System.out.println("-------------------------------------");System.out.println("uid: " + verify.getClaims().get("uid") + " name: " + verify.getClaims().get("name"));System.out.println("-------------------------------------");System.out.println("uid: " + verify.getClaim("uid") + " name: " + verify.getClaim("name"));}
输出:

注意:
withClaim 中,一个 key 只能对应一个 value,后面的 value 会覆盖前面的 valuewithArrayClaim(String name, xxx[] xxx) ,放多个 value验证令牌的过程: 验证签名(SignatureVerificationException) → token是否过期(TokenExpiredException) → 签名算法(AlgorithmMismatchException)
public class JWTUtils {// 盐值private static final String SALT = "LyeXro0VaE^!p";/*** @Description 创建token* @param map 负载map* @return String*/public static String getToken(Map map) {Calendar instance = Calendar.getInstance();instance.add(Calendar.DATE, 5);JWTCreator.Builder builder = JWT.create();map.forEach((k, v) -> {builder.withClaim(k, v);});String token = builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(SALT));return token;}/*** @Description 验证token合法性,不合法就会抛出异常* @param token */public static DecodedJWT verify(String token) {return JWT.require(Algorithm.HMAC256(SALT)).build().verify(token);}}
依赖:
com.auth0 java-jwt 3.19.3 com.baomidou mybatis-plus-boot-starter 3.4.1 org.projectlombok lombok com.alibaba druid-spring-boot-starter 1.2.11 mysql mysql-connector-java
配置文件:
# 应用名称
spring:application:name: jwt_demodatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/spbt?serverTimezone=GMT&characterEncoding=utf-8&useSSL=falseusername: rootpassword: admin# 应用服务 WEB 访问端口
server:port: 8088
表:

实体类:
@Data
public class User {private Integer id;private String name;private Character status;private String password;
}
mapper.xml:
mapper接口
@Mapper
public interface UserMapper extends BaseMapper {}
service:
public interface UserService extends IService {User login(User user);
}
@Service
public class UserServiceImpl extends ServiceImplimplements UserService{@Resourceprivate UserMapper userMapper;@Overridepublic User login(User user) {QueryWrapper wrapper = new QueryWrapper<>();wrapper.eq("name", user.getName());User userMsg = userMapper.selectOne(wrapper);if (userMsg == null) throw new RuntimeException("用户不存在, 登陆失败");if (!userMsg.getPassword().equals(user.getPassword())) throw new RuntimeException("密码错误, 登陆失败");return userMsg;}
}
controller:
@RestController
@Slf4j
public class Controller {@Resourceprivate UserService userService;@RequestMapping("/login")public Map login(User user) {Map map = new HashMap<>();try {User userMsg = userService.login(user);map.put("state", true);map.put("smg", "登陆成功");} catch (RuntimeException e) {map.put("state", false);map.put("smg", "登陆失败");e.printStackTrace();}return map;}
}
测试:

@RestController
@Slf4j
public class Controller {@Resourceprivate UserService userService;@RequestMapping("/login")public Map login(User user) {Map map = new HashMap<>();try {User userMsg = userService.login(user);// payloadMap payload = new HashMap<>();payload.put("id", userMsg.getId() + "");payload.put("name", userMsg.getName());payload.put("status", userMsg.getStatus() + "");// 生成令牌String token = JWTUtils.getToken(payload);map.put("state", true);map.put("smg", "登陆成功");map.put("token", token);} catch (RuntimeException e) {map.put("state", false);map.put("smg", "登陆失败");e.printStackTrace();}return map;}@RequestMapping("/test")public Map test(String token) {Map map = new HashMap<>();log.info("token:" + token);try {JWTUtils.verify(token);map.put("state", true);map.put("smg", "登陆成功");} catch (SignatureVerificationException e) {map.put("state", false);map.put("smg", "签名错误");} catch (TokenExpiredException e) {map.put("state", false);map.put("smg", "token过期");} catch (AlgorithmMismatchException e) {map.put("state", false);map.put("smg", "算法不一致");} catch (Exception e) {map.put("state", false);map.put("smg", "无效签名");}return map;}
}
拦截器:
public class JWTInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 获取请求头数据String token = request.getHeader("token");Map map = new HashMap<>();// 验证令牌try {JWTUtils.verify(token);return true; // 验证通过} catch (SignatureVerificationException e) {map.put("state", false);map.put("smg", "签名错误");} catch (TokenExpiredException e) {map.put("state", false);map.put("smg", "token过期");} catch (AlgorithmMismatchException e) {map.put("state", false);map.put("smg", "算法不一致");} catch (Exception e) {map.put("state", false);map.put("smg", "无效签名");}map.put("state", false);// 将map转换为json String json = new ObjectMapper().writeValueAsString(map);response.setContentType("application/json;character=UTF-8");response.getWriter().println(json);return false;}
}
注册拦截器:
@Configuration
public class InterceptorConf implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new JWTInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");}
}
test接口:
@RequestMapping("/test")public Map test(String token) {Map map = new HashMap<>();map.put("state", true);map.put("msg", "请求成功");return map;}
测试:
注意: 即使重启项目,用之前的 token 依然可以请求成功。