• JavaEE——Spring Boot + jwt


    目录

    什么是Spring Boot + jwt?

    如何实现Spring Boot + jwt:

    1. 添加依赖

    2、创建JWT工具类

    3. 定义认证逻辑

    4. 添加过滤器

     5、 http请求测试


    什么是Spring Boot + jwt?

    Spring Boot和JWT(JSON Web Token)是一对常见的组合,用于构建安全的Web应用程序。下面是它们的主要功能和如何结合使用的概览:

    1. Spring Boot:Spring Boot是一个用于快速构建基于Spring框架的Java应用程序的工具。它通过提供默认配置和约定大于配置的方式,简化了Spring应用程序的开发过程。

    2. JWT(JSON Web Token):JWT是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。JWT通常用于身份验证和信息传输,在Web应用程序中广泛应用。

    如何实现Spring Boot + jwt:

    1. 添加依赖

    ① 在你的 Spring Boot 项目中添加 JWT 相关的依赖,比如 jjwt 库,以便于创建和验证 JWT。

    1. io.jsonwebtoken
    2. jjwt
    3. 0.9.1

    ② 确保mybatis、mysql、spring boot、redis、druid、lombok等相关依赖存在

    ③ maven 刷新下载依赖

    2、创建JWT工具类

    ① 编写一个工具类来处理 JWT 的创建、解析和验证。这个类通常包含以下方法: - 创建 JWT:将用户信息(例如用户名、角色等)加密生成一个 token。

    1. public static String getToken(Map claims) {
    2. // JWT的签发时间
    3. long nowMillis = System.currentTimeMillis();
    4. Date now = new Date(nowMillis);
    5. // 指定签名的时候使用的签名算法
    6. SignatureAlgorithm signatureAlgotithm = SignatureAlgorithm.HS256;
    7. long expMillis = nowMillis + 604800000L; // 默认设置7天过期
    8. Date expirationDate = new Date(expMillis);
    9. String token = Jwts.builder() // 创建jwt builder
    10. .setClaims(claims) // 必须放最前面,不然后面设置的东西都会没有:如setExpiration会没有时间
    11. .setId(UUID.randomUUID().toString()) // jwt唯一标识
    12. .setIssuedAt(now) // 签发时间
    13. .setExpiration(expirationDate) // 过期时间
    14. .signWith(signatureAlgotithm, key) // 设置签名实用的签名算法和使用的密钥
    15. .compact();
    16. return token;
    17. }

     ② 编写一个工具类来处理 JWT 的创建、解析和验证。这个类通常包含以下方法: - 解析 JWT:从收到的 token 中提取用户信息

    1. public static Claims parseJwt(String token) throws Exception {
    2. String msg = null;
    3. try{
    4. Claims claims = Jwts.parser()
    5. .setAllowedClockSkewSeconds(604800) // 允许7天的偏移
    6. .setSigningKey(key) // 设置签名密钥
    7. .parseClaimsJws(token).getBody(); // 设置需要解析的JWT
    8. return claims;
    9. }catch (SignatureException se) {
    10. msg = "密钥错误";
    11. log.error(msg, se);
    12. throw new RuntimeException(msg);
    13. }catch (MalformedJwtException me) {
    14. msg = "密钥算法或者密钥转换错误";
    15. log.error(msg, me);
    16. throw new RuntimeException(msg);
    17. }
    18. catch (MissingClaimException mce) {
    19. msg = "密钥缺少校验数据";
    20. log.error(msg, mce);
    21. throw new RuntimeException(msg);
    22. }catch (ExpiredJwtException mce) {
    23. msg = "密钥已过期";
    24. log.error(msg, mce);
    25. throw new RuntimeException(msg);
    26. }catch (JwtException jwte) {
    27. msg = "密钥解析错误";
    28. log.error(msg, jwte);
    29. throw new RuntimeException(msg);
    30. }
    31. }

    3. 定义认证逻辑

    ① 在 controller 中,添加 @Slf4j 注解用于日志记录

    ② 在 controller 中,创建一个 login方法用来控制用户登入

    1. @PostMapping("/login")
    2. public Map login(@RequestBody User user) {
    3. log.info("user",user);
    4. log.info("用户名: [{}]", user.getName());
    5. log.info("密码: [{}]", user.getPwd());
    6. User u = userService.login(user);
    7. }

    ③ 在 login中 创新一个Map对象,承载认证结果和相关信息

    Map map = new HashMap<>();
    

    ④ 如果用户认证成功(u != null),则创建一个包含用户ID和名称的Map对象,并生成一个JWT令牌。接着在响应map中设置状态为true,消息为“认证成功”,并包含了生成的令牌。

    ⑤ 如果认证失败(u为空),则在响应map中设置状态为false,并包含了一个指示“用户名或者密码错误”的消息。 

    1. try {
    2. if (u != null) {
    3. Map payLoad = new HashMap<>();
    4. payLoad.put("id", u.getId());
    5. payLoad.put("name", user.getName());
    6. String token = JWTUtils.getToken(payLoad);
    7. map.put("state", true);
    8. map.put("message", "认证成功");
    9. map.put("token",token);
    10. } else {
    11. map.put("state", false);
    12. map.put("message", "用户名或者密码错误");
    13. }
    14. } catch (Exception e) {
    15. map.put("state", false);
    16. map.put("msg", e.getMessage());
    17. }
    18. return map;

    4. 添加过滤器

    ① 创建一个JWTInterceptor过滤器文件来检查传入的请求是否携带有效的 token,并根据需要进行相应的处理

    public class JWTInterceptor implements HandlerInterceptor {
    

     ② 创建preHandle方法,在请求处理之前执行,用于检查传入的请求是否携带有效的 token,并解析令牌

    1. @Override
    2. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    3. Map map = new HashMap<>();
    4. // 获取请求头中令牌
    5. String token = request.getHeader("token");
    6. if(!StringUtils.isEmpty(token)) {
    7. try {
    8. Claims claims = JWTUtils.parseJwt(token); // 如果找到令牌就使用 JWTUtils.parseJwt() 方法解析令牌
    9. return true; // 解析成功,即令牌有效,返回true
    10. } catch (RuntimeException e) { // 如果解析失败,会捕获 RuntimeException 异常
    11. e.printStackTrace();
    12. map.put("msg", e.getMessage()); // map.put("msg","密钥错误!");
    13. }
    14. }

    ③ 将异常信息放入 map 中,并设置一些响应信息,然后将信息以 JSON 格式返回给客户端

    1. map.put("message","token为null,必须携带token");
    2. map.put("state",false); // 设置状态
    3. // 将map 转为 json jackson
    4. String json = new ObjectMapper().writeValueAsString(map);
    5. response.setContentType("application/json;charset=UTF-8");
    6. response.getWriter().println(json);
    7. return false;
    8. }
    9. }

    ④ 再添加一个拦截器配置类 InterceptorConfig,用于配置和注册拦截器到 Spring MVC 中

    1. @Configuration
    2. public class InterceptorConfig implements WebMvcConfigurer {
    3. @Override
    4. public void addInterceptors(InterceptorRegistry registry) {
    5. String[] patterns = new String[] {"/auth/login","/*.html","/css/**","/js/**","/images/**","/layui/**"}; // 添加不拦截的方法
    6. registry.addInterceptor(new JWTInterceptor())
    7. .addPathPatterns("/**") // 其他接口token验证
    8. .excludePathPatterns(patterns); // 不进行token验证
    9. }
    10. }

     5、 http请求测试

     

  • 相关阅读:
    【文生图系列】基础篇-马尔可夫链
    【Go 基础篇】Go语言结构体实例的创建详解
    【Database System Concept 7th】Chapter 13读书笔记
    windows查看后台执行中的python或bat脚本
    微软官方操作系统(需空U盘)
    Java 线程池之ThreadPoolExecutor学习总结
    重点| 系统集成项目管理工程师考前50个知识点(2)
    接触非线性分析不收敛? 写给ABAQUS初学者的N个经验
    软件测试分类
    基尼系数的直观解释
  • 原文地址:https://blog.csdn.net/weixin_64916164/article/details/138091216