注册拦截器
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 缓存检测*/@Autowiredprivate RedisCacheInterceptor redisCacheInterceptor;/*** token检测*/@Autowiredprivate UserTokenInterceptor userTokenInterceptor;/*** 过滤器链 根据顺序拦截** @param registry 注册过滤器链 根据顺序拦截*/@Overridepublic 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 {@Autowiredprivate UserService userService;//将user对象放入threadLocal@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//效验handler 是否为匹配到controller的方法if (!(handler instanceof HandlerMethod)) {return true;}//判断方法是否包含了NoAuthorization注解, 标记不需要验证TOKENif (((HandlerMethod) handler).hasMethodAnnotation(NoAuthorization.class)) {return true;}//获取请求keyString 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对象@Overridepublic 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