# **拦截器** 作用:拦截用户登录认证以及权限 > 1. AdminAuthInterceptor 后台用户权限验证 > 2. AdminTokenInterceptor 后台用户登录token验证 > 3. FrontTokenInterceptor 移动端用户登录token验证 > 4. SwaggerInterceptor Swagger登录验证 1. PC后台访问除过一下接口,其余必须验证登录操作 ``` 1、登录 2、验证码 3、后台登录页面轮播图、LOGO ``` 2. 移动端会有三种情况 ``` 1、必须登录;用户中心、下单等接口 2、不需要登录;商品列表,首页接口等; 3、如果登录则取用户信息,否则不取,根据用户信息给出的数据不相同;优惠券接口 ``` 3. 如何配置以上三种情况,请仔细阅读以下代码 ``` package com.zbkj.crmeb.config; import com.filter.ResponseFilter; import com.interceptor.AdminAuthInterceptor; import com.interceptor.AdminTokenInterceptor; import com.interceptor.FrontTokenInterceptor; import com.interceptor.SwaggerInterceptor; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.handler.MappedInterceptor; //token验证拦截器 @Configuration public class WebConfig implements WebMvcConfigurer { // 这里使用一个Bean为的是可以在拦截器中自由注入,也可以在拦截器中使用SpringUtil.getBean 获取 // 但是觉得这样更优雅 //后台用户权限 @Bean public HandlerInterceptor adminAuthInterceptor(){ return new AdminAuthInterceptor(); } //后台用户登录 @Bean public HandlerInterceptor adminTokenInterceptor(){ return new AdminTokenInterceptor(); } //移动端用户登录 @Bean public HandlerInterceptor frontTokenInterceptor(){ return new FrontTokenInterceptor(); } @Bean public ResponseFilter responseFilter(){ return new ResponseFilter(); } @Value("${swagger.basic.username}") private String username; @Value("${swagger.basic.password}") private String password; @Value("${swagger.basic.check}") private Boolean check; @Override public void addInterceptors(InterceptorRegistry registry) { //添加token拦截器 //addPathPatterns添加需要拦截的命名空间; //excludePathPatterns添加排除拦截命名空间 //后台token拦截 registry.addInterceptor(adminTokenInterceptor()). addPathPatterns("/api/admin/**"). excludePathPatterns("/api/admin/validate/**"); //后台权限规则 registry.addInterceptor(adminAuthInterceptor()). addPathPatterns("/api/admin/**"). excludePathPatterns("/api/admin/validate/**"); //前端用户登录token registry.addInterceptor(frontTokenInterceptor()). addPathPatterns("/api/front/**"). excludePathPatterns("/api/front/qrcode/**"); } public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") .addResourceLocations("classpath:/static/"); registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } @Bean public FilterRegistrationBean filterRegister() { //注册过滤器 FilterRegistrationBean registration = new FilterRegistrationBean(responseFilter()); registration.addUrlPatterns("/*"); return registration; } /* 必须在此处配置拦截器,要不然拦不到swagger的静态资源 */ @Bean @ConditionalOnProperty(name = "swagger.basic.enable", havingValue = "true") public MappedInterceptor getMappedInterceptor() { return new MappedInterceptor(new String[]{"/swagger-ui.html", "/webjars/**"}, new SwaggerInterceptor(username, password, check)); } } ``` 4. 针对2.3如何处理? ``` 1、不做任何配置,让FrontTokenInterceptor来拦截 2、在FrontTokenInterceptor做部分路由判断;判断路由,部分路由不管用户是否登录都可以访问 3、看下面核心代码;在CheckFrontToken.checkRouter里配置路由即可 ``` ``` package com.interceptor; import com.alibaba.fastjson.JSONObject; import com.common.CheckFrontToken; import com.common.CommonResult; import com.utils.RequestUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //token验证拦截器 public class FrontTokenInterceptor implements HandlerInterceptor { @Autowired private CheckFrontToken checkFrontToken; //程序处理之前需要处理的业务 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { response.setCharacterEncoding("UTF-8"); String token = checkFrontToken.getTokenFormRequest(request); if(token == null || token.isEmpty()){ //判断路由,部分路由不管用户是否登录都可以访问 boolean result = checkFrontToken.checkRouter(RequestUtil.getUri(request)); if(result){ return true; } response.getWriter().write(JSONObject.toJSONString(CommonResult.unauthorized())); return false; } Boolean result = checkFrontToken.check(token, request); if(!result){ response.getWriter().write(JSONObject.toJSONString(CommonResult.unauthorized())); return false; } return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {} public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){} } ``` ``` package com.common; import com.constants.Constants; import com.utils.RedisUtil; import com.utils.RequestUtil; import com.utils.ThreadLocalUtil; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * 检测token是否过期 * Created on 2019/11/23 * @author zhangle */ @Component public class CheckFrontToken { @Autowired protected RedisUtil redisUtil; public Boolean check(String token, HttpServletRequest request){ try { boolean exists = redisUtil.exists(Constants.USER_TOKEN_REDIS_KEY_PREFIX + token); if(exists){ Object value = redisUtil.get(Constants.USER_TOKEN_REDIS_KEY_PREFIX + token); Map<String, Object> hashedMap = new HashMap<>(); hashedMap.put("id", value); ThreadLocalUtil.set(hashedMap); redisUtil.set(Constants.USER_TOKEN_REDIS_KEY_PREFIX +token, value, Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES); }else{ //判断路由,部分路由不管用户是否登录/token过期都可以访问 exists = checkRouter(RequestUtil.getUri(request)); } return exists; }catch (Exception e){ return false; } } //路由在此处,则返回true,无论用户是否登录都可以访问 public boolean checkRouter(String uri) { String[] routerList = { "api/front/product/detail", "api/front/coupons", "api/front/index" }; return ArrayUtils.contains(routerList, uri); } public String getTokenFormRequest(HttpServletRequest request){ return request.getHeader(Constants.HEADER_AUTHORIZATION_KEY); } } ```