<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
當一個資源從與該資源本身所在的伺服器不同的域或埠請求一個資源時,資源會發起一個跨域 HTTP 請求。
出於安全原因,瀏覽器限制從指令碼內發起的跨源HTTP請求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 這意味著使用這些API的Web應用程式只能從載入應用程式的同一個域請求HTTP資源,除非使用CORS標頭檔案。
如果前端提示”Access-Control-Allow-Origin”問題
XMLHttpRequest cannot load http://xxxxxxxxxx/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
那麼需要再SpringBoot2設定跨域過濾器允許跨域存取。
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; @Component public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, GET"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); chain.doFilter(req, res); } @Override public void init(FilterConfig filterConfig) {} @Override public void destroy() {} }
如果需要顯示跨域地址,還可以在裡面加上存取來源列印語句,供排查
String curOrigin = request.getHeader("Origin"); System.out.println("###跨域過濾器->當前存取來源->"+curOrigin+"###");
如果需要跨域許可權,可以判斷一下來源
String curOrigin = request.getHeader("Origin"); System.out.println("###跨域過濾器->當前存取來源->"+curOrigin+"###"); if(curOrigin.indexOf("127.0.0.1:8080")>-1){ response.setHeader("Access-Control-Allow-Origin", "*"); }
關於跨域存取更專業的內容,可以存取Mozilla官方的一個關於CROS文章
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
請求url的協定、域名、埠三者有任意一個不同即為跨域。跨域問題是因為瀏覽器的同源策略的限制而產生的。
同源策略的限制:
瀏覽器的同源策略會限制跨域請求,限制的方式一般有兩種:
一般瀏覽器都是第二種方式限制跨域請求,那就是說請求已到達伺服器,並有可能對資料庫裡的資料進行了操作,但是返回的結果被瀏覽器攔截了,那麼我們就獲取不到返回結果,這是一次失敗的請求,但是可能對資料庫裡的資料產生了影響。
為了防止這種情況的發生,規範要求,對這種可能對伺服器資料產生副作用的HTTP請求方法,瀏覽器必須先使用OPTIONS方法發起一個預檢請求,從而獲知伺服器是否允許該跨域請求:如果允許,就傳送帶資料的真實請求;如果不允許,則阻止傳送帶資料的真實請求。
解決非同源內容無法互動的問題,目前主流的解決方案就是:CORS(跨域資源共用)。
跨域資源共用(Cross-origin Resource Sharing)簡稱CORS,它突破了一個請求在瀏覽器發出只能在同源的情況下向伺服器獲取資料的限制。
CORS約定伺服器端和瀏覽器在HTTP協定之上,通過一些額外HTTP頭部資訊,進行跨域資源共用的協商。伺服器端和瀏覽器都必需遵循規範中的要求。
CORS把HTTP的跨域請求分成兩類,簡單請求和非簡單請求,不同請求按照不同的策略進行跨域資源共用協商。
簡單跨域請求需滿足的條件:
1.請求方法是GET、HEAD或者POST(POST時,Content-Type的值必須是application/x-www-form-urlencoded、multipart/form-data、text/plain中的一個值);
2.請求中沒有自定義HTTP請求頭。
HTTP頭只能時下面這些欄位:
Accept
Accept-Language
Content-Language
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type
以上兩點都滿足才是簡單跨域請求。
對於簡單跨域請求,處理方式如下:
1.瀏覽器要做的就是在HTTP請求頭中新增Origin,將JavaScript指令碼所在域填充進去,向其他域的伺服器請求資源。
Origin: http://www.joker.com
Origin欄位用來說明,本次請求來自哪個源(協定 + 域名 + 埠)。伺服器根據這個值,決定是否同意這次請求。
2.伺服器端收到一個簡單跨域請求後,根據資源許可權設定,在響應頭中新增Access-Control-Allow-Origin。
如果Origin指定的源,不在許可範圍內,伺服器會返回一個正常的HTTP迴應。 但這個響應頭資訊沒有包含Access-Control-Allow-Origin欄位,瀏覽器就知道該域名不在許可範圍內。
如果Origin指定的域名在許可範圍內,伺服器返回的響應,會多出幾個頭資訊欄位:
Access-Control-Allow-Origin: http://www.joker.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: My-Token
Access-Control-Allow-Origin
:該欄位是必須的。它的值要麼是請求時Origin欄位的值,要麼是一個*值,表示接受任意域名的請求。Access-Control-Allow-Credentials
: 該欄位是可選的。它的值是一個布林值,表示是否允許傳送Cookie。預設情況下,Cookie不包括在CORS請求之中。設為true,即表示伺服器明確許可,Cookie可以包含在請求中,一起發給伺服器。這個值也只能設為true,如果伺服器不要瀏覽器傳送Cookie,刪除該欄位即可。Access-Control-Expose-Headers
:該欄位是可選的。CORS請求時,XMLHttpRequest物件的getResponseHeader()方法只能拿到6個基本欄位:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他欄位,就必須在Access-Control-Expose-Headers裡面指定。3.瀏覽器收到響應後,通過獲取響應頭中的Access-Control-Allow-Origin欄位,來判斷如果當前域已經得到授權,則將結果返回給JavaScript。否則瀏覽器忽略此次響應。
非簡單跨域請求需滿足的條件:
以上兩點只要至少滿足其中一點就是非簡單跨域請求。
對於非簡單跨域請求,處理方式如下:
1.瀏覽器在傳送真實HTTP請求之前先傳送一個OPTIONS的預檢請求,檢測伺服器端是否支援真實請求進行跨域資源存取。
真實請求的資訊在OPTIONS請求中通過請求頭中的Access-Control-Request-Method和Access-Control-Request-Headers欄位來描述。此外與簡單跨域請求一樣,請求頭中也會有Origin欄位。
Origin: http://www.joker.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: Header1,Header2
Origin
:必須欄位,用於指定請求源。Access-Control-Request-Method
:必須欄位,用於描述真實請求的方法(PUT、DELETE等)。Access-Control-Request-Headers
:指定真實請求會額外傳送的請求頭欄位資訊。2.伺服器端接到預檢請求後,會檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers欄位,檢驗是否允許跨源請求。
如果不允許該跨域請求,會返回一個正常的HTTP迴應,但這個響應頭資訊沒有包含Access-Control-Allow-Origin欄位,瀏覽器就知道該域名不在許可範圍內。
如果允許該跨域請求,就會在響應頭中放入Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers,分別表示允許跨域資源請求的域、請求方法和請求頭。此外,伺服器端還可以在響應頭中放入Access-Control-Max-Age,允許瀏覽器在指定時間內,無需再傳送預檢請求進行協商,直接用本次協商結果即可。
Access-Control-Allow-Origin: http://www.joker.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: Header1,Header2,Header3 Access-Control-Allow-Credentials: true Access-Control-Max-Age: 1728000
Access-Control-Allow-Methods
:該欄位必需,它的值是逗號分隔的一個字串,表明伺服器支援的所有跨域請求的方法。注意,返回的是所有支援的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預檢"請求。Access-Control-Allow-Headers
:如果瀏覽器請求包括Access-Control-Request-Headers欄位,則Access-Control-Allow-Headers欄位是必需的。它也是一個逗號分隔的字串,表明伺服器支援的所有頭資訊欄位,不限於瀏覽器在"預檢"中請求的欄位。Access-Control-Allow-Credentials
: 該欄位與簡單請求時的含義相同。它的值是一個布林值,表示是否允許傳送Cookie。預設情況下,Cookie不包括在CORS請求之中。設為true,即表示伺服器明確許可,Cookie可以包含在請求中,一起發給伺服器。這個值也只能設為true,如果伺服器不要瀏覽器傳送Cookie,刪除該欄位即可。Access-Control-Max-Age
: 該欄位可選,用來指定本次預檢請求的有效期,單位為秒。上面結果中,有效期是20天(1728000秒),即允許快取該條迴應1728000秒(即20天),在此期間,不用發出另一條預檢請求。瀏覽器根據OPTIONS請求返回的結果來決定是否繼續傳送真實的請求進行跨域資源存取。這個過程對真實請求的呼叫者來說是透明的。
SpringBoot設定CORS的的本質都是通過設定響應頭資訊來告訴前端該請求是否支援跨域。
SpringBoot設定CORS的方式主要有以下三種。
1. 設定過濾器CorsFilter
@Configuration public class CorsConfig { @Bean CorsFilter corsFilter() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList("*")); configuration.setAllowedHeaders(Arrays.asList("*")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return new CorsFilter(source); } }
2. 實現介面WebMvcConfigurer
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedHeaders("*") .allowedMethods("*") .allowCredentials(true); } }
3. 使用註解@CrossOrigin
@CrossOrigin註解可以用在類或者方法上
用在控制器類上,表示 該類的所有方法都允許跨域
@RestController @CrossOrigin public class TestController { @GetMapping("test") public String test() { return "success"; } }
用在控制器方法上,表示該方法都允許跨域
@RestController public class TestController { @CrossOrigin @GetMapping("test") public String test() { return "success"; } }
@CrossOrigin註解原始碼
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CrossOrigin { /** * 這origins和value是一樣的 * 允許來源域名的列表,例如 www.baidu.com,匹配的域名是跨域預請求Response頭中的Access-Control-Aloow_origin欄位值。 * 不設定確切值時預設支援所有域名跨域存取。 */ @AliasFor("origins") String[] value() default {}; @AliasFor("value") String[] origins() default {}; /** * 高版本下Spring2.4.4使用originPatterns而不是value和origins */ String[] originPatterns() default {}; /** * 跨域請求中允許的請求頭中的欄位型別, 該值對應跨域預請求Response頭中的Access-Control-Allow-Headers欄位值。 * 不設定確切值預設支援所有的header欄位(Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma)跨域存取 */ String[] allowedHeaders() default {}; /** * 跨域請求請求頭中允許攜帶的除Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma這六個基本欄位之外的其他欄位資訊, * 對應的是跨域請求Response頭中的Access-control-Expose-Headers欄位值 */ String[] exposedHeaders() default {}; /** * 跨域HTTP請求中支援的HTTP請求型別(GET、POST...), * 不指定確切值時預設與 Controller 方法中的 methods 欄位保持一致。 */ RequestMethod[] methods() default {}; /** * 瀏覽器是否將本域名下的cookie資訊攜帶至跨域伺服器中。預設攜帶至跨域伺服器中,但要實現cookie共用還需要前端在AJAX請求中開啟withCredentials屬性。 * 該值對應的是是跨域請求 Response 頭中的 'Access-Control-Allow-Credentials' 欄位值。 */ String allowCredentials() default ""; /** * 該值的目的是減少瀏覽器預檢請求/響應互動的數量。預設值1800s。設定了該值後,瀏覽器將在設定值的時間段內對該跨域請求不再發起預請求。 * 該值對應的是是跨域請求Response頭中的Access-Control-Max-Age欄位值,表示預檢請求響應的快取持續的最大時間。 */ long maxAge() default -1; }
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45