【跨域】SpringBoot跨域,攔截器中,第一次獲取的請求頭為NULL,發送兩次請求的處理方式


背景:

在做前后端分離時,牽扯到跨域,但是已經設置了跨域
前端設置了允許攜帶Cookie
axios.defaults.withCredentials = true;
后端也配置了跨域

瀏覽器端查看發送的請求,請求頭中包含Authorization



原因:

實際上發送了兩次請求,第一次為OPTIONS請求,第二次才GET/POST...請求

  • OPTIONS請求中,不會攜帶請求頭的參數,所以在攔截器上獲取請求頭為空,自定義的攔截器攔截成功
  • 第一次請求不能通過,就不能獲取第二次的請求了GET/POST...
  • 第一次請求不帶參數,第二次請求才帶參數

解決:

在攔截器中,如果請求為OPTIONS請求,讓 OPTIONS 請求返回一個200狀態碼,表示可以正常訪問,然后就會收到真正的GET/POST請求

String method = request.getMethod();	//輸出 OPTIONS/GET/POST。。。
//如果是 OPTIONS 請求,讓 OPTIONS 請求返回一個200狀態碼
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
    response.setStatus(HttpServletResponse.SC_OK);
    return false;
}



攔截器完整示例

@Component
public class HttpRequestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //origin:指定可以訪問本項目的IP
        String origin = request.getHeader("Origin");
        response.setContentType("application/json;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", origin);
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "1800");
        //  設置  受支持請求標頭(自定義  可以訪問的請求頭  例如:Token)
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,token,Origin,Content-Type,Accept");
        // 指示的請求的響應是否可以暴露於該頁面。當true值返回時它可以被暴露
        response.setHeader("Access-Control-Allow-Credentials", "true");
        //如果是OPTIONS請求,讓其響應一個 200狀態碼,說明可以正常訪問
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

配置攔截器

自定義的攔截器必須要配置,才能使用

@Configuration
public class WebConfig implements WebMvcConfigurer {

	@Autowired
    private HttpRequestInterceptor httpRequestInterceptor;
    
    // 配置攔截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //設置跨域得攔截器 ,/** 表示攔截所有請求
        registry.addInterceptor(httpRequestInterceptor).addPathPatterns("/**");
    }
}


免責聲明!

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



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