• SpringBoot整合JWT+Vue


    • 引入pom
           <!--引入JWT-->
            <dependency>
                <groupId>com.auth0</groupId>
                <artifactId>java-jwt</artifactId>
                <version>3.10.0</version>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 编写工具类
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTCreator;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.interfaces.DecodedJWT;
    
    import java.util.Calendar;
    import java.util.Map;
    
    /**
     * @Description: JWT工具类
     */
    public class JWTUtils {
        //秘钥
        private static final String SIGNATURE = "aef7aaf174fa0143ce765a7efd869313";
        //过期时间为1天
       public static  final Integer EXPIRATION_TIME= 1* 24 * 60 * 60;
    
    
    
        /**
         * 生成token
         * @param payload token需要携带的信息
         * @return token字符串
         */
        public static String getToken(Map<String,String> payload){
            // 指定token过期时间为1天
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.SECOND, EXPIRATION_TIME);
            JWTCreator.Builder builder = JWT.create();
            // 构建payload
            payload.forEach((k,v) -> builder.withClaim(k,v));
            // 指定过期时间和签名算法
            return  builder.withExpiresAt(calendar.getTime()).sign(Algorithm.HMAC256(SIGNATURE));
        }
    
    
    
    
        /**
         * 验证token
         * @param token
         */
        public static void verify(String token){
            JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
        }
    
        /**
         * 获取token中payload
         * @param token
         * @return
         */
        public static DecodedJWT getPayload(String token){
            return JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
        }
    
    }
    
    
    • 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
    
    /**
     * 状态码枚举
     */
    public enum CodeEnum {
    
        /**操作成功**/
        SUCCESS(200,"操作成功"),
        /**服务调用异常**/
        SERVICE_CALL_EXCEPTION(400,"服务调用异常"),
        /**操作失败**/
        ERROR(500,"操作失败"),
        /**参数不合法**/
        ILLEGAL_PARAMETER(5001,"参数不合法"),
        /**验证码已失效**/
        VERIFICATION_CODE_FAILURE(5002,"验证码已失效"),
        /**用户昵称重复**/
        DUPLICATE_NICKNAME(5003,"用户昵称重复"),
        /**用户名或密码错误**/
        LOGIN_FAILED(5004,"用户名或密码错误"),
        /**文件上传失败**/
        FILE_UPLOAD_FAILED(5005,"文件上传失败"),
        /**资源不存在*/
        RESOURCE_DOES_NOT_EXIST(5006,"资源不存在"),
        /**无效签名**/
        JWT_INVALID(2001,"无效签名"),
        /**token过期**/
        JWT_OVERDUE(2002,"token过期"),
        /**token算法不一致**/
        JWT_ALGORITHM_INCONSISTENCY(2003,"token算法不一致"),
        /**token失效**/
        JWT_LOSE_EFFECT(2004,"token失效"),
        /**非法请求**/
        ILLEGAL_REQUEST(2005,"非法请求,请求来源不合法");
    
        /**
         * 自定义状态码
         **/
        private Integer code;
        /**自定义描述**/
        private String message;
    
        CodeEnum(Integer code, String message){
            this.code = code;
            this.message = message;
        }
    
        public Integer getCode() {
            return code;
        }
        public String getMessage() {
            return message;
        }
    }
    
    
    • 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
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * 请求信息类,用于返回请求是否成功
     * @param 
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class CommonResult<T>{
        /**
         * 响应状态码
         */
        private int code;
    
        /**
         * 响应结果描述
         */
        private String message;
    
        /**
         * 返回的数据
         */
        private T data;
    
        /**
         * 成功返回
         * @param data
         * @param 
         * @return
         */
        public static <T> CommonResult<T> success(T data) {
            CommonResult<T> response= new CommonResult<>();
            response.setCode(CodeEnum.SUCCESS.getCode());
            response.setMessage(CodeEnum.SUCCESS.getMessage());
            response.setData(data);
            return response;
        }
    
        /**
         *  失败返回,自定义code
         * @param code
         * @param message
         * @param 
         * @return
         */
        public static <T> CommonResult<T> fail(Integer code, String message) {
            CommonResult<T> response = new CommonResult<>();
            response.setCode(code);
            response.setMessage(message);
            return response;
        }
    
        /**
         *  失败返回
         * @param codeEnum
         * @param 
         * @return
         */
        public static <T> CommonResult<T> fail(CodeEnum codeEnum) {
            CommonResult<T> response = new CommonResult<>();
            response.setCode(codeEnum.getCode());
            response.setMessage(codeEnum.getMessage());
            return response;
        }
        /**
         *  失败返回
         * @param message
         * @param 
         * @return
         */
        public static <T> CommonResult<T> fail(String message) {
            CommonResult<T> response = new CommonResult<>();
            response.setCode(CodeEnum.ERROR.getCode());
            response.setMessage(message);
            return response;
        }
    
    }
    
    
    • 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
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 编写请求拦截器
    import cn.hutool.core.util.StrUtil;
    import com.auth0.jwt.exceptions.AlgorithmMismatchException;
    import com.auth0.jwt.exceptions.SignatureVerificationException;
    import com.auth0.jwt.exceptions.TokenExpiredException;
    import com.example.vehicleinformationsystem.bean.CodeEnum;
    import com.example.vehicleinformationsystem.bean.CommonResult;
    import com.example.vehicleinformationsystem.util.JWTUtils;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * @Description: jwt拦截器
     */
    @Component
    public class JWTInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //获取请求头中存放的令牌token
            String token = request.getHeader("Authorization");
            CommonResult<CodeEnum> result=new CommonResult();
            try {
                if(StrUtil.isNotBlank(token)){
                    //验证令牌
                    JWTUtils.verify(token);
                    return true;
                }else{
                    result.setCode(CodeEnum.JWT_INVALID.getCode());
                    result.setMessage(CodeEnum.JWT_INVALID.getMessage());
                }
    
            } catch (SignatureVerificationException e) {
                e.printStackTrace();
    
                result.setCode(CodeEnum.JWT_INVALID.getCode());
                result.setMessage(CodeEnum.JWT_INVALID.getMessage());
            } catch (AlgorithmMismatchException e) {
                e.printStackTrace();
                result.setCode(CodeEnum.JWT_ALGORITHM_INCONSISTENCY.getCode());
                result.setMessage(CodeEnum.JWT_ALGORITHM_INCONSISTENCY.getMessage());
            } catch (TokenExpiredException e) {
                e.printStackTrace();
                result.setCode(CodeEnum.JWT_OVERDUE.getCode());
                result.setMessage(CodeEnum.JWT_OVERDUE.getMessage());
    
            } catch (Exception e) {
                e.printStackTrace();
                result.setCode(CodeEnum.JWT_OVERDUE.getCode());
                result.setMessage(CodeEnum.JWT_OVERDUE.getMessage());
            }
    
    
            //将map转为json,返回给前端
            String json = new ObjectMapper().writeValueAsString(result);
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().print(json);
            return false;
        }
    }
    
    
    • 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
    • 61
    • 62
    • 63
    • 注册拦截器
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
     * @Description: 注册拦截器
     */
    
    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
        @Autowired
        private JWTInterceptor jwtInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(jwtInterceptor)
                    //拦截所有请求
                    .addPathPatterns("/**")
                    //不需要拦截的请求
                    .excludePathPatterns("/system/login","/system/addUser");
        }
    
    }
    
    
    • 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
    • 测试
      1.不携带token
      在这里插入图片描述
      返回结果:
      在这里插入图片描述
      2.携带token

    在这里插入图片描述

    • 整合Vue

    1.解决跨域问题

    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 GlobalCorsConfig {
    
        @Bean
        public CorsFilter corsFilter() {
            //1.添加CORS配置信息
            CorsConfiguration config = new CorsConfiguration();
            config.addAllowedOriginPattern("*");
            //2) 是否发送Cookie信息
            config.setAllowCredentials(true);
            //3) 允许的请求方式
            config.addAllowedMethod("OPTIONS");
            config.addAllowedMethod("HEAD");
            config.addAllowedMethod("GET");
            config.addAllowedMethod("PUT");
            config.addAllowedMethod("POST");
            config.addAllowedMethod("DELETE");
            config.addAllowedMethod("PATCH");
            // 4)允许的头信息
            config.addAllowedHeader("*");
            // 4)有效时间
            config.setMaxAge(3600L);
    
            //2.添加映射路径,我们拦截一切请求
            UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
            configSource.registerCorsConfiguration("/**", config);
    
            //3.返回新的CorsFilter.
            return new CorsFilter(configSource);
        }
    }
    
    
    • 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

    2.登录成功返回token

     /**
         * 登录
         *
         * @param userInfo
         * @return
         */
        @PostMapping(value = "/login")
        public CommonResult<Map<String,Object>> login(@RequestBody Map<String,Object>  userInfo) {
            if(userInfo!=null){
               		if("admin".equals(userInfo.get("nickName"))&&"admin".equals(userInfo.get("password"))){
               		//设置token需要返回的信息
                        Map<String,String> tokenMap=new HashMap<>();
                        tokenMap.put("id","111");
                        tokenMap.put("nickName",userInfo.get("nickName"));
                        result.put("token",JWTUtils.getToken(tokenMap));
    
                        return CommonResult.success(result);
               		}
                }
    
            return CommonResult.fail("用户昵称或密码错误");
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3.Vue将登录成功后接收到的token存储在浏览器

    //登录请求	
    login(this.param).then(res => {
    	console.log("登录请求结果--》》", res);
    //判断是否登录成功
    if (res.code == 200) {
    	this.$message.success('登录成功');
    	localStorage.setItem('token', res.data.token);
    } else {
    	this.$message.error('用户昵称或密码错误');
    }
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.每次请求时,携带token(此处可以在vue编写一个请求前置拦截器,这样携带token这个步骤就可以降低冗余,此处略)

    /**
     *删除用户信息
     * @param {*} param 
     */
    export const deleteUser = param => {
        return request({
            url: '/system/deleteUser/'+ param,
            method: 'GET',
    		headers:{ //向headers中添加token
    			Authorization:localStorage.getItem("token")
    		}
        });
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    网络协议 — IPv6 互联网协议第 6 版
    SQL 朝花夕拾 [保持更新]
    用iPad开发iPhone App,苹果发布Swift Playgrounds 4
    中国建成世界海中最高5G基站 采用微波传输方案
    结构型设计模式之代理模式
    【leetcode速通java版】02——有序数组、子数组、螺旋矩阵
    大数据从入门到实战 - MapReduce基础实战
    利用procrank和lsof定位出客户软件内存OOM的问题
    05 【nodejs内置模块(上)】
    2023-09-09青少年软件编程(C语言)等级考试试卷(一级)解析
  • 原文地址:https://blog.csdn.net/qq_46122292/article/details/127632698