前端
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)
-
在pom.xml文件中导入相关依赖
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
-
生成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; } }
-
添加两个相关注解
//用来跳过验证的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; }
-
添加一个拦截器判断访问该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 { } }
-
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(); } }
-
使用
在controller中需要进行token验证的方法中添加@UserLoginToken