Bootstrap

【Java】spring boot生成jwt,并使用filter进行校验

1. 引入依赖

使用hutool依赖来操作jwt;lombok来记日志

<!--hutool-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.13</version>
</dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
        <!--日志依赖-->
<dependency>
    <!--用于注解 @Slf4j中,-->
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>

2. 添加配置

在application.yml中添加jwt 的秘钥,以及过期时间,
secretKey:秘钥
expireSeconds:过期时间,10分钟

jwt:
  secretKey: KxK7f3yaSfOXVwvuYJDozvQ7Mt1JnqRX
  expireSeconds: 10

3. 编写JwtUtil 工具类

package com.manager.oa.util.security;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

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

/**
 * @Author sms
 * @Version V1.0.0
 * @Date 2022-08-09
 */
@Component
@Slf4j
public class JwtUtil {

    // 秘钥
    @Value("${jwt.secretKey}")
    private String secretKey;
    // 过期时间
    @Value("${jwt.expireSeconds}")
    private String expireSeconds;


    {
        log.debug("【jwtUtil】secretKey->{}",secretKey);
    }

    /**
     * 产生Token
     *
     * @param map 需要载荷的数据 map类
     * @return
     */
    public String createJWT(Map<String, Object> map) {
        //当前时间
        DateTime now = DateTime.now();
        // 设置过期时间
        DateTime newTime = now.offsetNew(DateField.MINUTE, Integer.parseInt(expireSeconds));

        Map<String, Object> payload = new HashMap<String, Object>();
        //签发时间
        payload.put(JWTPayload.ISSUED_AT, now);
        //过期时间
        payload.put(JWTPayload.EXPIRES_AT, newTime);
        //生效时间
        payload.put(JWTPayload.NOT_BEFORE, now);
        //载荷
        Set<String> keySet = map.keySet();
        for (String key : keySet
        ) {
            payload.put(key, map.get(key));
        }
        // 产生Token
        return JWTUtil.createToken(payload, secretKey.getBytes());
    }

   /**
     * 验证
     *
     * @param token
     * @return
     */
    public boolean verifyJWT(String token) {
        JWT jwt = JWTUtil.parseToken(token);
        boolean verifyKey = jwt.setKey(secretKey.getBytes()).verify();
        return verifyKey;
    }

    /**
     * 验证时间是否过期
     *
     * @param token
     * @return
     */
    public boolean verifyTimeJWT(String token) {
        try {
            JWTValidator.of(token).validateDate(DateUtil.date());
            return true;
        } catch (ValidateException e) {
            e.printStackTrace();
            return false;
        }
    }
}

4. 添加filter校验

1)编写TokenFilter

package com.manager.oa.filter;

import com.manager.oa.util.security.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @Author sms
 * @Version V1.0.0
 * @Date 2022-08-10
 */
@Slf4j
public class TokenFilter implements Filter {
    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.debug("【过滤器】:进入到token验证过滤器-》");
        /*
        token验证
         */
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        log.debug("【filter】uri->{}", httpServletRequest.getRequestURI());
        // 放行登录请求
        if (httpServletRequest.getRequestURI().equals("/login")) {
            chain.doFilter(httpServletRequest, response);
        } else {
            String token = httpServletRequest.getHeader("X-Token");
            log.debug("【filter】验证token...->{}", token);
            log.debug("【filter】jwtUtil->{}", jwtUtil);
            if (jwtUtil.verifyJWT(token)) {
                chain.doFilter(httpServletRequest, response);
            }
        }
    }

    @Override
    public void destroy() {

    }

}

2)将TokenFilter交给spring管理

在Application中添加配置
在这里插入图片描述

 // token校验过滤器
    @Bean
    public FilterRegistrationBean myTokenFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        // 不能new 需要交给spring管理后,单独写方法调用 ,否则为null
        filterRegistrationBean.setFilter(this.TokenExpireFilter());
        // 添加过滤路径
        filterRegistrationBean.addUrlPatterns("/*");
        // 保证在所有过滤之前执行
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }

    @Bean
    public Filter TokenExpireFilter() {
        return new TokenFilter();
    }

5. 测试

login

@PostMapping("/login")
    public ResponseEntity<?> doLogin(@RequestBody User user) {
        log.debug("【系统日志】:->正在登录;携带的参数:{}", user);
        user.setPassword(DigestUtils.md5Hex(user.getPassword()));
        User DBUser = userService.getUserByLogin(user);
        if (DBUser == null) {
            log.debug("【系统日志】:{}->登录失败;", user.getAccount());
            return new ResponseEntity<>(false, "500", "账号或密码错误", null);
        } else {
            log.debug("【系统日志】:{}->登录成功;", user.getAccount());
            Map<String, Object> map = new HashMap<>();
            map.put("account", DBUser.getAccount());
            map.put("id", DBUser.getId());
            String token = jwtUtil.createJWT(map);
            log.debug("【系统日志】Token->{}", token);
            return new ResponseEntity<>(token);
        }
    }
 @RequestMapping("/")
    public ResponseEntity<List<Menu>> getIndex(HttpServletRequest request) {
        String token = request.getHeader("X-Token");
        log.debug("【系统日志】进入到首页, 前端返回的token->{}", token);
        JWT jwt = JWTUtil.parseToken(token);
        // jwt.getPayload("id")取出数据
        User DBUser = userService.getById((Integer) jwt.getPayload("id"));
        List<Menu> menuList = new ArrayList<>();
		return new ResponseEntity<>(menuList);
}
;