• SpringBoot集成JWT(极简版):



    在这里插入图片描述

    1.JWT依赖
    
    <dependency>
        <groupId>com.auth0groupId>
        <artifactId>java-jwtartifactId>
        <version>3.10.3version>
     dependency>
    
    <dependency>
    	<groupId>cn.hutoolgroupId>
    	<artifactId>hutool-allartifactId>
    	<version>5.7.20version>
    dependency>
    <dependency>
    	<groupId>org.apache.poigroupId>
    	<artifactId>poi-ooxmlartifactId>
    	<version>4.1.2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    2.JWT工具类TokenUtils.java
    package com.example.springboot.utils;
    
    import cn.hutool.core.date.DateUtil;
    import cn.hutool.core.util.StrUtil;
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.example.springboot.entity.User;
    import com.example.springboot.service.IUserService;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Date;
    
    @Component
    public class TokenUtils {
    
        private static IUserService staticUserService;
    
        @Resource
        private IUserService userService;
    
        @PostConstruct
        public void setUserService() {
            staticUserService = userService;
        }
    
        /**
         * 生成token
         *
         * @return
         */
        public static String genToken(String userId, String sign) {
            return JWT.create().withAudience(userId) // 将 user id 保存到 token 里面,作为载荷
                    .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2小时后token过期
                    .sign(Algorithm.HMAC256(sign)); // 以 password 作为 token 的密钥
        }
    
        /**
         * 获取当前登录的用户信息
         *
         * @return user对象
         */
        public static User getCurrentUser() {
            try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                String token = request.getHeader("token");
                if (StrUtil.isNotBlank(token)) {
                    String userId = JWT.decode(token).getAudience().get(0);
                    return staticUserService.getById(Integer.valueOf(userId));
                }
            } catch (Exception e) {
                return null;
            }
            return null;
        }
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    3.token示例
    {"username":"admin","password":"admin","nickname":"管理员11111","avatarUrl":"https://img-blog.csdnimg.cn/c6d0ece75d3f4833bd820b8aa2eb952b.png","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxIiwiZXhwIjoxNjQ0MzgxMDI4fQ.87nwS8ENDOu6RY-4PTLBBzXfDv6-5TiQLQhBXrYGb700"}
    
    • 1
    4.拦截器JwtInterceptor.java
    package com.example.springboot.config.interceptor;
    
    import cn.hutool.core.util.StrUtil;
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.exceptions.JWTDecodeException;
    import com.auth0.jwt.exceptions.JWTVerificationException;
    import com.example.springboot.common.Constants;
    import com.example.springboot.entity.User;
    import com.example.springboot.exception.ServiceException;
    import com.example.springboot.service.IUserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class JwtInterceptor implements HandlerInterceptor {
    
        @Autowired
        private IUserService userService;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
            String token = request.getHeader("token");
            // 如果不是映射到方法直接通过
            if(!(handler instanceof HandlerMethod)){
                return true;
            }
            // 执行认证
            if (StrUtil.isBlank(token)) {
                throw new ServiceException(Constants.CODE_401, "无token,请重新登录");
            }
            // 获取 token 中的 user id
            String userId;
            try {
                userId = JWT.decode(token).getAudience().get(0);
            } catch (JWTDecodeException j) {
                throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
            }
            // 根据token中的userid查询数据库
            User user = userService.getById(userId);
            if (user == null) {
                throw new ServiceException(Constants.CODE_401, "用户不存在,请重新登录");
            }
            // 用户密码加签验证 token
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
            try {
                jwtVerifier.verify(token); // 验证token
            } catch (JWTVerificationException e) {
                throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
            }
            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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    5.拦截器设置InterceptorConfig.java
    package com.example.springboot.config;
    
    import com.example.springboot.config.interceptor.JwtInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(jwtInterceptor())
                    .addPathPatterns("/**")  // 拦截所有请求,通过判断token是否合法来决定是否需要登录
                    .excludePathPatterns("/api/user/login", "/api/user/register", "/**/export", "/**/import");
        }
    
        @Bean
        public JwtInterceptor jwtInterceptor() {
            return new JwtInterceptor();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    6.统一接口WebConfig.java
    package com.example.springboot.config;
    
    /**
     * @Author SunPeng
     * @Date 2022/10/31 20:26
     * @description 请输入描述
     */
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class WebConfig implements  WebMvcConfigurer {
        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
            // 指定controller统一的接口前缀
            configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    7.设置自定义头配置 CorsConfig .java
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    @Configuration
    public class CorsConfig {
    
        @Bean
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
            corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
            corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
            source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
            return new CorsFilter(source);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    8.GlobalExceptionHandler.java
    package com.example.springboot.exception;
    
    import com.example.springboot.common.Result;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @Author SunPeng
     * @Date 2022/10/28 14:56
     * @description 请输入描述
     */
    @ControllerAdvice
    public class GlobalExceptionHandler {
        /**
         * 如果抛出的的是ServiceException,则调用该方法
         * @param se 业务异常
         * @return Result
         */
        @ExceptionHandler(ServiceException.class)
        @ResponseBody
        public Result handle(ServiceException se){
            return Result.error(se.getCode(), se.getMessage());
        }
    }
    
    • 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
    9.ServiceException.java
    package com.example.springboot.exception;
    
    import lombok.Getter;
    
    /**
     * @Author SunPeng
     * @Date 2022/10/28 14:58
     * @description 自定义异常
     */
    @Getter
    public class ServiceException extends RuntimeException{
        private String code;
    
        public ServiceException(String code,String msg){
            super(msg);
            this.code=code;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    10.设置token:

    在这里插入图片描述

    String token=TokenUtils.genToken(one.getId().toString(),one.getPassword());
    userDTO.setToken(token);
    
    • 1
    • 2
    11.最终效果:

    在这里插入图片描述

  • 相关阅读:
    零基础自学javase黑马课程第十五天
    基于java+SpringBoot+VUE+Mysql+微信小程序物业管理系统
    MySQL的Json类型个人用法详解
    [CISCN2019 华北赛区 Day1 Web2]ikun
    力扣(LeetCode)176. 第二高的薪水(2022.06.25)
    基于opencv的实时睡意检测系统
    SQL SERVER安装配置及问题解决方案
    使用React和ResizeObserver实现自适应ECharts图表
    Win11系统/RTX30系列显卡——安装gpu版pytorch
    ubuntu18.04安装QT5
  • 原文地址:https://blog.csdn.net/weixin_53791978/article/details/127626819