• SpringBoot整合JWT


    SpringBoot整合JWT

    什么是JWT:https://www.jianshu.com/p/576dbf44b2ae

    一、导入依赖

    <dependency>
        <groupId>com.auth0groupId>
        <artifactId>java-jwtartifactId>
        <version>3.19.2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、生成JWT

    @Component
    @Slf4j
    public class TokenUtils {
    
        private static UserService staticUserService;
    
        @Autowired
        private UserService userService;
    
        @PostConstruct
        public void setStaticUserService() {
            staticUserService = userService;
        }
    
    	// 重点 生成token
        public static  String genToken(String userId, String sign) {
            return JWT.create()
                    .withAudience(userId)   // 载荷
                    .withExpiresAt(DateUtil.offsetMinute(new Date(), 10))   // 10分钟后token过期
                    .sign(Algorithm.HMAC256(sign)); // 以password作为token密钥
        }
    
        // 根据载荷中的id获取当前用户信息 
        public static User getCurrentUser() {
            User user = null;
            try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                String token = request.getHeader("token");
                if (StrUtil.isNotBlank(token)) {
                    String userId = JWT.decode(token).getAudience().get(0);
                    user = staticUserService.getById((Integer.valueOf(userId)));
                }
            } catch (JWTDecodeException | NumberFormatException e) {
                log.error(e.toString());
            }
            return user;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在登录的接口中调用该方法,将生成的token返回给前端

    @Override
    public UserDTO login(UserDTO userDTO) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("ds_user_name", userDTO.getUsername())
                .eq("ds_user_password", userDTO.getPassword());
        User user = null;
        try {
            user = getOne(wrapper);
            if (user != null) {
                userDTO.setUsername(user.getDsUserName());
                String token = TokenUtils.genToken(user.getDsUserId().toString(), user.getDsUserPassword());
                userDTO.setToken(token );
                userDTO.setPassword(null);
            } else {
                userDTO = null;
            }
        } catch (Exception e) {
            log.error(e.toString());
            userDTO = null;
        }
        return userDTO;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    三、前端接收token

    将传回的token存放在浏览器中:

    this.api.userApi.signIn(this.user)
            .then(res => {
              if (res.code === '200') {
                localStorage.setItem('user', JSON.stringify(res.data))
                this.$router.push("/home")
                this.$message.success('登录成功!')
              }
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    并在request.js中加上这一段,让每个请求都带上token

    request.interceptors.request.use(config => {
        config.headers['Content-Type'] = 'application/json;charset=utf-8';
        let user = JSON.parse(localStorage.getItem('user'))
        if (user) config.headers['token'] = user.token;  // 设置请求头
        return config
    }, error => {
        return Promise.reject(error)
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    四、后端验证token

    因为每个请求头中都包含当前用户的token,所以我们可以做一个拦截器,让非法请求无法获得数据:

    实现HandlerInterceptor接口

    @Component
    @Slf4j
    public class JwtInterceptor implements HandlerInterceptor {
        @Autowired
        UserService userService;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String token = request.getHeader("token");
            // 检查方法是否需要过滤
            if (!(handler instanceof HandlerMethod)) return true;
    
            // 初步验证token
            if (StrUtil.isBlank(token)) {
                log.error("不要乱搞");
                return false;
            }
            String userId;
            try {
                userId = JWT.decode(token).getAudience().get(0);
                // 查看是否有该用户
                User user = userService.getById(Integer.valueOf(userId));
                if (user == null) {
                    log.error("不要乱搞");
                    return false;
                } else {
                    // 验证签证
                    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getDsUserPassword())).build();
                    jwtVerifier.verify(token);
                }
            } catch (JWTDecodeException e) {
                e.printStackTrace();
                log.error(e.toString());
            }
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    五、配置拦截器

    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
        @Autowired
        JwtInterceptor jwtInterceptor;
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(jwtInterceptor)
                    .addPathPatterns("/**")
                    // 不能直接 **/login必须加 /
                    .excludePathPatterns("/**/login", "swagger/**", "/swagger-ui.html", "swagger-ui.html", "/webjars/**", "/swagger-ui.html/*", "/swagger-resources", "/swagger-resources/**");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    [ffmpeg] x264 配置参数解析
    Docker理论— 虚拟化技术分类
    Windows 安装 RabbitMq
    FFmpeg —— 点播流程技术总结(公网、局域网)
    如何把一个空项目变成SpringBoot项目
    NFT艺术品有什么用?真的会有人买吗?
    Apache SeaTunnel社区成功入选开源之夏活动,现开启导师招募!
    煤矿皮带撕裂检测系统
    C++基础语法(继承)
    信息差也能赚钱?具体是怎么做的?看完这个你就懂了!
  • 原文地址:https://blog.csdn.net/yangsf_/article/details/126142389