SpringBoot+vue+token

前端

token验证

1、前端接受后台发过来的token,将其存入LocalStorage,并且在store.js中进行存储

 state: {
    // 存储token
    Authorization: localStorage.getItem('Authorization') ? localStorage.getItem('Authorization') : ''
  },
  mutations: {
    // 修改token,并将token存入localStorage
    changeLogin (state, user) {
      state.Authorization = user.Authorization;
      localStorage.setItem('Authorization', user.Authorization);
    },
    logout(state) {
      localStorage.removeItem('Authorization');
      localStorage.removeItem('user');

      state.token = null
    }
  },

2、路由守卫:将没有登录信息的访问请求全部转到login.vue,有相关信息则放行

router.beforeEach((to, from, next) => { // 路由跳转前监控(保证登录状态)
  // 重登陆删除本地数据
  if (to.path === '/login') {
    sessionStorage.removeItem('user')
  }
  let user = JSON.parse(sessionStorage.getItem('user'))
  // 登录验证:如果本地没有储存用户且不在登录页面则跳转
  if (!user && to.path !== '/login') {
    next({ path: '/login' })
  } else {
    next()
  }
})

3、配置请求头:这里使用axios,所以在axios的配置文件中添加:

axios.interceptors.request.use(
    config => {
      if (localStorage.getItem('Authorization')) {
        config.headers.Authorization = localStorage.getItem('Authorization');
      }
   
      return config;
    },
    error => {
      return Promise.reject(error);
    });

//http response 拦截器
axios.interceptors.response.use(
  response => {
      return response;
  },
  error => {
      if (error.response) {
          console.log(this);
          Vue.$store.commit("logout");
          Vue.$router.push({ path: "/login" });
      }
      return Promise.reject(error.response.data)
});

后端

token验证(集成jwt)
  1. 在pom.xml文件中导入相关依赖

          <dependency>
                <groupId>com.auth0</groupId>
                <artifactId>java-jwt</artifactId>
                <version>3.4.0</version>
            </dependency>
    
  2. 生成token

    @Service
    public class TokenService {
        public String getToken(User user) {
            Date start = new Date();
            long currentTime = System.currentTimeMillis() + 60 * 60 * 1000;//一小时有效时间
            Date end = new Date(currentTime);
            String token = "";
    
            token = JWT.create().withAudience(user.getUid().toString()).withIssuedAt(start).withExpiresAt(end)
                    .sign(Algorithm.HMAC256(user.getPassword()));
            return token;
        }
    }
    
  3. 添加两个相关注解

    //用来跳过验证的PassToken
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PassToken {
        boolean required() default true;
    }
    
    //需要登录才能进行操作的注解UserLoginToken
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface UserLoginToken {
        boolean required() default true;
    }
    
  4. 添加一个拦截器判断访问该controller是否需要验证token

    public class tokenInterceptor implements HandlerInterceptor {
            @Autowired
            UserService userService;
    
        /**
         *          预处理回调,判断每个处理器是否符合要求,返回true表示符合要求,放行
         *          这里主要是对user的id和password进行解密,如果要改变,还需要改变生成token的service
         * @param httpServletRequest
         * @param httpServletResponse
         * @param object
         *          拦截的对象
         * @return
         * @throws Exception
         */
            @Override
            public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
                String token = httpServletRequest.getHeader("Authorization");// 从 http 请求头中取出 token
                // 如果不是映射到方法直接通过
                if(!(object instanceof HandlerMethod)){
                    return true;
                }
                HandlerMethod handlerMethod=(HandlerMethod)object;
                Method method=handlerMethod.getMethod();
                //检查是否有passtoken注释,有则跳过认证
                if (method.isAnnotationPresent(PassToken.class)) {
                    PassToken passToken = method.getAnnotation(PassToken.class);
                    if (passToken.required()) {
                        return true;
                    }
                }
                //检查有没有需要用户权限的注解
                if (method.isAnnotationPresent(UserLoginToken.class)) {
                    UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
                    if (userLoginToken.required()) {
                        // 执行认证
                        if (token == null) {
                            throw new RuntimeException("无token,请重新登录");
                        }
                        // 获取 token 中的 user id
                        String userId;
                        try {
                            userId = JWT.decode(token).getAudience().get(0);
                        } catch (JWTDecodeException j) {
                            //jwt解码失败
                            throw new RuntimeException("401");
                        }
                            User user = userService.findUserById(userId);
                            if (user == null) {
                                throw new RuntimeException("用户不存在,请重新登录");
                            }
                            // 验证 token
                            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
                            try {
                                jwtVerifier.verify(token);
                            } catch (JWTVerificationException e) {
                                throw new RuntimeException("401");
                        }
                        //将验证通过后的用户信息放到请求中
                        httpServletRequest.setAttribute("currentUser", user);
                        return true;
                    }
                }
                return true;
            }
    
        /**
         *         处理器执行之后,视图解析器渲染之前 执行的回调
         * @param httpServletRequest
         * @param httpServletResponse
         * @param o
         *         处理器执行后返回的数据
         * @param modelAndView
         * @throws Exception
         */
            @Override
            public void postHandle(HttpServletRequest httpServletRequest,
                                   HttpServletResponse httpServletResponse,
                                   Object o, ModelAndView modelAndView) throws Exception {
    
            }
    
        /**
         *          视图解析器将视图解析之后的回调
         * @param httpServletRequest
         * @param httpServletResponse
         * @param o
         * @param e
         * @throws Exception
         */
            @Override
            public void afterCompletion(HttpServletRequest httpServletRequest,
                                        HttpServletResponse httpServletResponse,
                                        Object o, Exception e) throws Exception {
            }
    
    }
    
  5. jwt的配置类

    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
       @Override
       public void addInterceptors(InterceptorRegistry registry) {
           registry.addInterceptor(authenticationInterceptor())
                   .addPathPatterns("/**");    // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
       }
       @Bean
       public tokenInterceptor authenticationInterceptor() {
           return new tokenInterceptor();
       }
    }	
    
  6. 使用

    在controller中需要进行token验证的方法中添加@UserLoginToken

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值