SpringBoot解決跨域問題的3種方案


問題背景:
Same Origin Policy(SOP同源策略):具有相同的Origin即擁有相同的協議、主機地址及端口。
目的是防止某個文檔或者腳本從多個不同源的地址裝載(其他站點轉載內容不安全)。

CORS簡介
跨域資源共享(CORS:Cross-origin resource sharing):它允許瀏覽器向跨源服務器發出XMLHTTP Request請求,從而克服了AJAX只能同源使用的限制。CORS需要瀏覽器和服務器同時支持,它的通信由瀏覽器自動完成,不需要用戶參與。CORS通信的關鍵在於服務器,服務器需要實現CORS接口。

CORS請求分兩類
瀏覽器發出的CORS簡單請求,只需要在頭信息中增加一個Origin字段。

  1. 簡單請求(simple request):HEAD、GET、POST請求,並且HTTP的頭信息僅為以下幾種字段:
    Accept、Accept-Language、Content-Language、Last-Event-ID、
    Content-Type(僅限3個值:application/x-www-form-urlencoded、multipart/form-data、text/plain)
  2. 非簡單請求(not-so-simple):不在簡單請求范圍的為非簡單請求。
    瀏覽器發出非簡單請求會在正式通信之前增加一次OPTIONS查詢請求,稱為“預檢”請求(preflight)。瀏覽器先訪問服務器,當前網頁所在域名是否在服務器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復,瀏覽器才會正式發出XMLHttpRequest請求,否則報錯。

詳解響應頭

  • Access-Control-Allow-Origin(必填):請求時Origin字段的具體值或者*(表示接受任意域名的請求)
  • Access-Control-Allow-Methods(必填):逗號分割的一個具體字符串或者*,表示服務器支持的所有跨域請求方法。返回的是所有支持的方法而不單是瀏覽器請求的那個方法,避免多次“預檢”請求。
  • Access-Control-Expose-Headers(可選):CORS請求XMLRequest對象的getResponseHeader方法只能拿到6個基本字段(Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma)如果需要拿到其他字段,就必須在這里指定。
  • Access-Control-Allow-Credentials(可選):布爾值(表示是否允許發送Cookie,默認false),對服務器有特殊要求的請求(PUT、DELETE、Content-Type的類型為application/json)時這個值只能為true,如果服務器不需要瀏覽器發送Cookie,刪除即可。
  • Access-Control-Max-Age(可選):指定本次預檢請求的有效期,單位為秒,有效期內不用再發預檢請求。如果發現開發中每次請求都是2條(一次是OPTIONS,一次是正常請求)那么就需要配置此字段,避免每次都發出預檢請求。

三種解決方案:

  1. 全局配置,實現WebMvcConfigurer接口的addCorsMappings方法Github示例代碼
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")
                // 是否允許發送Cookie
                .allowCredentials(true)
                // 本次預檢請求的有效期,單位為秒
                .maxAge(3600)
                .allowedHeaders("*");
    }
}
  1. 全局Filter配置,實現javax.servlet.Filter接口的doFilter方法Github示例代碼
@Configuration
@WebFilter(filterName = "corsFilter")
public class CorsFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        filterChain.doFilter(servletRequest,response);
    }
}
  1. @CrossOrigin注解,類似@RequestMapping注解的使用(最小粒度的控制,精確到單個請求級別)
    一般使用前兩種全局配置即可,同時配置就近原則生效。


免責聲明!

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



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