/** * 自定義攔截器類 */ 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); } }