0


Spring Boot + jwt

文章目录

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

② maven 刷新下载依依赖

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

① 在utils包下新建一个工具类JWTUtils.java来处理 JWT 的创建、解析和验证。这个类通常包含以下方法: - 创建 JWT:将用户信息加密生成一个 token。

  private static final String key = "abc1234";    // 签名时使用的secret 
    public static String getToken(Map<String, Object> claims) {
        // JWT的签发时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        // 指定签名的时候使用的签名算法
        SignatureAlgorithm signatureAlgotithm = SignatureAlgorithm.HS256;
        long expMillis = nowMillis + 604800000L;        // 默认设置7天过期
        Date expirationDate = new Date(expMillis);
        String token = Jwts.builder()               // 创建jwt builder
                .setClaims(claims)                      // 必须放最前面,不然后面设置的东西都会没有:如setExpiration会没有时间
                .setId(UUID.randomUUID().toString())     // jwt唯一标识
                .setIssuedAt(now)                                    // 签发时间
                .setExpiration(expirationDate)                 // 过期时间
                .signWith(signatureAlgotithm, key)          // 设置签名实用的签名算法和使用的密钥
                .compact();
        return token;
    }

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

  public static Claims parseJwt(String token) throws Exception {
      String msg = null;
      try{
          Claims claims = Jwts.parser()
                .setAllowedClockSkewSeconds(604800) // 允许7天的偏移
                .setSigningKey(key)                         // 设置签名密钥
                .parseClaimsJws(token).getBody(); // 设置需要解析的JWT
          return claims;
      }catch (SignatureException se) {
          msg = "密钥错误";
          log.error(msg, se);
          throw new RuntimeException(msg);
      }catch (MalformedJwtException me) {
          msg = "密钥算法或者密钥转换错误";
          log.error(msg, me);
          throw new RuntimeException(msg);
 }catch (MissingClaimException mce) {
            msg = "密钥缺少校验数据";
            log.error(msg, mce);
            throw new RuntimeException(msg);

        }catch (ExpiredJwtException mce) {
            msg = "密钥已过期";
            log.error(msg, mce);
            throw new RuntimeException(msg);

        }catch (JwtException jwte) {
            msg = "密钥解析错误";
            log.error(msg, jwte);
            throw new RuntimeException(msg);
        }
    }

定义认证逻辑

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

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

@PostMapping("/login")
public Map<String, Object> login(@RequestBody Map<String, Object> userMap) {
        // 打印了包含两个参数的日志信息
        log.info("userMap: {}", userMap);
        // 调用返回List<User>的方法
        List<User> userList = userService.login(userMap);

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

Map<String, Object> map = new HashMap<>();

④ 如果用户认证成功(userList不为空且不是空列表),则创建一个包含用户ID和名称的Map对象,并使用JWTUtils工具类生成一个JWT令牌。接着在响应map中设置状态为true,消息为“认证成功”,并包含了生成的令牌。

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

 try {
            if (userList != null && !userList.isEmpty()) {
                // 如果列表不为空,表示认证成功
                User u = userList.get(0);  // 假设取第一个用户
                Map<String, Object> payLoad = new HashMap<>();
                payLoad.put("id", u.getId());
                payLoad.put("userName", u.getUserName());
                String token = JWTUtils.getToken(payLoad);
                map.put("state", true);
                map.put("message", "认证成功");
                map.put("token", token);
            } else {
                // 如果列表为空,表示用户名或密码错误
                map.put("state", false);
                map.put("message", "用户名或者密码错误");
            }
        } catch (Exception e) {
            map.put("state", false);
            map.put("msg", e.getMessage());
        }
        return map;
    }

添加过滤器

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

public class JWTInterceptor implements HandlerInterceptor {

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

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

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

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

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

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

http请求测试

新建http请求进行测试(使用postman或者其他方法均可)

POST http://localhost:8080/login
Content-Type: application/json
{
  "user_name": "zly",
  "password": "124"
}
###
GET http://localhost:8080/getUser/zly
token:eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjIiLCJ1c2VyTmFtZSI6InpseSIsImV4cCI6MTcwMTc2MzM5NiwiaWF0IjoxNzAxMTU4NTk2LCJqdGkiOiIxMzA4YWJiYi1jODY5LTQyZTAtYWM5Yi01Y2IyYzdhNWI1N2QifQ.BA4NNDCoUxOyAApPkzSadAWJl4F_F2qbv1_pKOxEwlY

1、认证成功

2、用户名或者密码错误

3、无token直接访问

4、携带token访问

使用postman

标签: spring boot 后端

本文转载自: https://blog.csdn.net/weixin_63831348/article/details/139820808
版权归原作者 小柯82 所有, 如有侵权,请联系我们删除。

“Spring Boot + jwt”的评论:

还没有评论