一、問題
使用前后端分離模式開發項目時,往往會遇到這樣一個問題 -- 無法跨域獲取服務端數據
這是由於瀏覽器的同源策略導致的,目的是為了安全。在前后端分離開發模式備受青睞的今天,前端和后台項目往往會在不同的環境下進行開發,這時就會出現跨域請求數據的需求,目前的解決方案主要有以下幾種:
JSONP、iframe、代理模式、CORS等等
前面幾種方式在這里不講,網上有很多資料。在這里我主要分享一下CORS這種解決方式,CORS即“跨域資源共享”,它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
使用 CORS 跨域的時候和普通的 ajax 過程是一樣的,只是瀏覽器在發現這是一個跨域請求的時候會自動幫我們處理一些事情,所以說只要服務端提供支持,前端是不需要做額外的事情的。
二、實現
實現的大概思路是這樣的,首先使用過濾器獲取請求對象request的信息,比如Origin 字段(表示請求來自哪個源,包括協議、域名、端口),通過預先配置的參數判斷請求是否合法,然后設置響應對象response的頭信息,實現跨域資源請求。在介紹實現方式之前我們先來了解一下會用到的響應頭信息。
響應頭
-
Access-Control-Allow-Methods
用來列出瀏覽器的CORS請求允許使用的HTTP方法,如:GET、POST、PUT、DELETE、OPTIONS
OPTIONS方法介紹:跨域時,瀏覽器會先發一次OPTIONS請求:OPTIONS 方法在跨域請求(CORS)中的應用
-
Access-Control-Allow-Credentials
表示是否支持跨域Cookie -
Access-Control-Allow-Headers
逗號分隔的字符串,表示服務器支持的所有頭信息字段,如Content-Type以及自定義的字段,前端往后端發送的header頭如果未在Access-Control-Allow-Headers配置,則會跨域失敗
-
Access-Control-Expose-Headers
與“Access-Control-Allow-Headers”相反,表示不支持的頭信息字段 -
Access-Control-Allow-Origin
允許跨域的請求源信息,包括協議、域名、端口,為*
表示允許所有請求來源,服務端會校驗前端請求header參數中的Origin參數
spring boot java配置如下:
package com.rh.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class CorsConfig{ @Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允許cookies跨域 config.addAllowedOrigin("*");// #允許向該服務器提交請求的URI,*表示全部允許,自定義可以添加多個,在SpringMVC中,如果設成*,會自動轉成當前請求頭中的Origin config.addAllowedHeader("header1");// #允許訪問的頭信息,*表示全部,可以添加多個 config.setMaxAge(18000L);// 預檢請求的緩存時間(秒),即在這個時間段里,對於相同的跨域請求不會再預檢了 config.addAllowedMethod("OPTIONS");// 允許提交請求的方法,*表示全部允許,一般OPTIONS,GET,POST三個夠了 config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }
測試頁面:里面傳入了一個沒有被允許的header:header2
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus®"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <title>prd page</title> <script src="../js/jquery.min.js"></script> <script> $(document).ready(function(){ $.ajax({url:"http://127.0.0.1:8002/test/test2", headers:{"header2":"aaaa"},success:function(result){ $("#div1").html(result); }}); }); </script> </head> <body> <div id="div1"><h2>使用 jQuery AJAX 修改文本內容</h2></div> </body> </html>
會提示跨域失敗
備注:跨域只能在html中用ajax測試 不能再postman等測試工具中測試(postman用的是類似於httpclient實現的,而不是ajax方式去請求,所以無法測試跨域問題)
本文參考
https://www.jianshu.com/p/d6dc9e60c8e6
https://blog.csdn.net/puma_dong/article/details/51395976