Spring Boot - 設置請求攔截和接口token驗證


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM