/** * 自定义拦截器类 */ public class V8Interceptor implements HandlerInterceptor { @Autowired private Environment env; //自动注入环境变量获取配置 @Autowired private StringRedisTemplate redisTmp; // token规则为 user-reids-token:userId : UUID private static String USER_REDIS_TOKEN = "api-token"; /** * 判断用户是否登录 * 若用户 username 不存在,则为未登录 * 若用户 username 存在,则判断 usertoken 是否存在 * 若存在,则用户状态为已登录 * 若不存在,则用户状态为登录超时 * @param request * @param response * @param handler * @return * @throws Exception * */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 如果是 嗅探请求,则直接放行 String methodname = request.getMethod(); if("OPTIONS".equals(methodname)){ return true; } //例如:/api/wx/getmsg String requrl = request.getRequestURI(); if ( (requrl.indexOf("/api/wx/")>=0) ){ //针对移动端接口的拦截处理 String local_wxapitoken = env.getProperty("wxapitoken"); String req_wxapitoken = request.getHeader("wxapitoken"); if (!local_wxapitoken.equals(req_wxapitoken)){ //再判断是否提供了username和usertoken String username = request.getHeader("username"); String userOldToken = request.getHeader("usertoken"); String v8_acname = env.getProperty("acname"); String errormsg = checkUserTokenInfo(username,userOldToken,acname); if (errormsg.equals("")){ return true; }else{ String info = "无效的wxapitoken或usertoken"; returnErrorResponse(response, JsonUtils.getErrorJson("1000", info)); return false; } }else{ return true; } } else{ //其他情况处理 String username = request.getHeader("username"); String userOldToken = request.getHeader("usertoken"); String v8_acname = env.getProperty("acname"); String errormsg = checkUserTokenInfo(username,userOldToken,acname); if (errormsg.equals("")){ return true; }else{ returnErrorResponse(response, JsonUtils.getErrorJson("1000", errormsg)); return false; } } //判断username和usertoken是否合法 //返回:空字符表示正确,其他表示错误原因 public String checkUserTokenInfo(String username,String userOldToken,String acname){ String errormsg = ""; if (StrUtils.isNotBlank(username) && StrUtils.isNotBlank(userOldToken)) { //token的key名称格式 api-token:acname:username String userTokenKey = USER_REDIS_TOKEN + ":" + acname + ":" + username; String userToken = ""; if (redisTmp.hasKey(userTokenKey)) { userToken = redisTmp.opsForValue().get(userTokenKey).toString(); } // 用户有token,但最新token为空,说明登录状态过期 if (StrUtils.isBlank(userToken)) { errormsg = "登录过期或未登录,请重新登录"; return errormsg; } // 两个token不一致,可能是恶意用户乱填token if (!userOldToken.equals(userToken)) { errormsg = "无效token,请重新登录"; return errormsg; } } else { System.out.println("该用户没有登录"); errormsg = "请登录后再操作"; return errormsg; } return errormsg; } public void returnErrorResponse(HttpServletResponse response, String jsonstr) throws IOException { OutputStream outputStream = null ; try { response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); outputStream = response.getOutputStream(); outputStream.write(jsonstr.getBytes("UTF-8")); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if(outputStream != null){ outputStream.close(); } } } }
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Bean public V8Interceptor vxInterceptor(){ return new V8Interceptor(); } @Override public void addCorsMappings(CorsRegistry registry) { //添加映射路径 registry.addMapping("/**") .allowedOrigins("*") //是否发送Cookie信息, allowedOrigins设置*,则allowCredentials不能设置true .allowCredentials(false) //放行哪些原始域(请求方式) .allowedMethods("GET","POST", "PUT", "DELETE") //放行哪些原始域(头部信息) .allowedHeaders("*") //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) .exposedHeaders("username", "usertoken","wxapitoken","lan_ip","net_ip"); } /** * 设置拦截的url路径 * * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry){ //设置要拦截的接口或目录 List listOfVerify = Arrays.asList( "/api/file/**", "/api/wx/**" ); //设置要拦截的接口 List listOfExc = Arrays.asList( "/api/login/changeUserPwd" ); registry.addInterceptor(vxInterceptor()) .addPathPatterns(listOfVerify) .excludePathPatterns(listOfExc); super.addInterceptors(registry); } }