要想弄明白什么是跨域就要知道什么是同源策略,要想知道什么是同源策略就要先知道什么是源。
下表給出了相對http://store.company.com/dir/page.html同源檢測的示例:
URL 結(jié)果 原因
http://store.company.com/dir2/other.html 成功
http://store.company.com/dir/inner/another.html 成功
https://store.company.com/secure.html 失敗 不同協(xié)議 ( https和http )
http://store.company.com:81/dir/etc.html 失敗 不同端口 ( 81和80)
http://news.company.com/dir/other.html 失敗 不同域名 ( news和store )
同源策略是瀏覽器的一個安全限制,從一個源加載的文檔或者腳本默認不能訪問另一個源的資源。例如a.com/111/html頁面不能訪問b.com/person這種接口,因為他們是不用的源。
注意:下面幾個不受同源策略限制
1、頁面中鏈接(例如頁面的<a href="http://www.w3school.com.cn">W3School</a>)、重定向和表單提交不受同源策略限制
2、跨域資源的引入是不受同源策略的限制,但是js讀不到其中的內(nèi)容。<script src="..."></script>,<img>,<link>,<iframe>等。
介紹生產(chǎn)中最常用的兩種解決跨域的方法。CORS解決跨域問題和通過代理解決跨域問題。
CORS是Cross-Origin Resources Sharing的簡寫,中文翻譯為“跨域資源共享”,是W3C的標準。通過CORS,瀏覽器允許向其他源服務(wù)器發(fā)送資源請求。
設(shè)置CORS需要瀏覽器和服務(wù)器兩個方面支持。目前基本上主流的瀏覽器都支持CORS(IE 8 和 9 需要通過 XDomainRequest 來實現(xiàn)),所以只要后端服務(wù)支持CORS,就能夠?qū)崿F(xiàn)跨域。服務(wù)端設(shè)置 Access-Control-Allow-Origin 就可以開啟 CORS。 該屬性表示哪些域名可以訪問資源,如果設(shè)置通配符(*)則表示所有網(wǎng)站都可以訪問資源。要實現(xiàn)CORS跨域其實非常簡單,說白了就是在服務(wù)端設(shè)置一系列的HTTP頭,主要分為請求頭和響應(yīng)頭,在請求和響應(yīng)時加上這些HTTP頭即可輕松實現(xiàn)CORS。
雖然設(shè)置 CORS 和前端沒什么關(guān)系,但是通過這種方式解決跨域問題的話,會在發(fā)送請求時出現(xiàn)兩種情況,分別為簡單請求和復(fù)雜請求。針對不同的情況,服務(wù)端的設(shè)置也不一樣。
簡單請求
只要同時滿足以下兩大條件,就屬于簡單請求
條件 1:使用下列方法之一:
GET
HEAD
POST
條件 2:Content-Type 的值僅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
復(fù)雜請求
不符合以上條件的請求就肯定是復(fù)雜請求了。
復(fù)雜請求的 CORS 請求,會在正式通信之前,增加一次 HTTP 查詢請求,稱為"預(yù)檢"請求,該請求是 option 方法的,通過該請求來向服務(wù)端詢問從當前源發(fā)送請求以及允許的請求方法和請求字段。
HTTP請求頭:
#請求域Origin: ”http://localhost:8080“#這兩個屬性只出現(xiàn)在預(yù)檢請求中,即OPTIONS請求Access-Control-Request-Method: ”POST“Access-Control-Request-Headers: ”content-type“
HTTP響應(yīng)頭:
#允許向該服務(wù)器提交請求的URI,*表示全部允許,在SpringMVC中,如果設(shè)成*,會自動轉(zhuǎn)成當前請求頭中的OriginAccess-Control-Allow-Origin: ”http://localhost:8080“#允許訪問的頭信息Access-Control-Expose-Headers: "Set-Cookie"#預(yù)檢請求的緩存時間(秒),即在這個時間段里,對于相同的跨域請求不會再預(yù)檢了Access-Control-Max-Age: ”1800”#允許Cookie跨域,在做登錄校驗的時候有用Access-Control-Allow-Credentials: “true”#允許提交請求的方法,*表示全部允許Access-Control-Allow-Methods:GET,POST,PUT,DELETE,PATCH
例如簡單請求
請求頭:
響應(yīng)頭:
springboot里面可以這樣設(shè)置
@Configurationpublic class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .maxAge(3600); }}
實現(xiàn)原理:同源策略是瀏覽器需要遵循的標準,而如果是請求都發(fā)給代理服務(wù)器代理服務(wù)器再向后端服務(wù)器請求就可以規(guī)避跨域的問題。
例如用nginx做代理服務(wù)器。
nginx配置
server{ # 監(jiān)聽80端口 listen 80; # 域名是localhost server_name localhost; #凡是localhost:8080/api這個樣子的,都轉(zhuǎn)發(fā)到真正的服務(wù)端地址http://localhost:8080 location ^~ /api { proxy_pass http://localhost:8080; } }