注册拦截器
package com.tanhua.server.config;
import com.tanhua.server.interceptor.RedisCacheInterceptor;
import com.tanhua.server.interceptor.UserTokenInterceptor;
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;
/**
* 配置过滤器
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* redis 缓存检测
*/
@Autowired
private RedisCacheInterceptor redisCacheInterceptor;
/**
* token检测
*/
@Autowired
private UserTokenInterceptor userTokenInterceptor;
/**
* 过滤器链 根据顺序拦截
*
* @param registry 注册过滤器链 根据顺序拦截
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.userTokenInterceptor).addPathPatterns("/**");
registry.addInterceptor(this.redisCacheInterceptor).addPathPatterns("/**");
}
}
编写用户线程工具类
package com.tanhua.common.utils;
import com.tanhua.common.pojo.User;
/**
* 当前用户线程
*/
public class UserThreadLocal {
private UserThreadLocal() {
}
private static final ThreadLocal<User> LOCAL = new ThreadLocal<>();
/**
* 将user放到threadLocal
*
* @param user user
*/
public static void setUser(User user) {
LOCAL.set(user);
}
/**
* 返回当前线程中的user对象
*
* @return 返回当前线程中的user对象
*/
public static User getUser() {
return LOCAL.get();
}
/**
* 删除当前线程中的user对象
*/
public static void remove() {
LOCAL.remove();
}
}
定义标记不需要验证token 的注解
package com.tanhua.common.utils;
import java.lang.annotation.*;
/**
* 标记不需要验证token 的方法
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented //标记注解
public @interface NoAuthorization {
}
拦截器
package com.tanhua.server.interceptor;
import com.tanhua.common.pojo.User;
import com.tanhua.common.utils.NoAuthorization;
import com.tanhua.common.utils.UserThreadLocal;
import com.tanhua.server.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 拦截 效验token
*/
@Component
public class UserTokenInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
//将user对象放入threadLocal
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//效验handler 是否为匹配到controller的方法
if (!(handler instanceof HandlerMethod)) {
return true;
}
//判断方法是否包含了NoAuthorization注解, 标记不需要验证TOKEN
if (((HandlerMethod) handler).hasMethodAnnotation(NoAuthorization.class)) {
return true;
}
//获取请求key
String token = request.getHeader("Authorization");
if (StringUtils.isNotEmpty(token)) {
//调用sso 验证 token 的有效性
User user = userService.queryUserByToken(token);
if (null != user) {
UserThreadLocal.setUser(user);
return true;
}
}
//token 无效 401无权限
response.setStatus(401);
return false;
}
//完成方法:从threadLocal中删除user对象
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserThreadLocal.remove();
}
}
定义过滤器。 注册获取器。 拦截到请求。如果命中controller的方法, 判断该方法@NoAuthorization 有没有使用自定义注解标记。不需要token拦截。如果没有就拦截。拿到请求token 验证token 。如果token合法
UserThreadLocal.setUser(user); 将用户信息。放到ThreadLocal用户线程。
在service 中。就那可以拿到user用户信息了。不用每个service 方法都校验一次token