瀏覽器跨域的那些事

整理中

目標:

了解跨域

解決跨域

服務器配置跨域(java, nginx)

前端調試時配置解決跨域

一、什么是跨域

當資源請求來自不同域,協(xié)議或端口的資源時,資源會發(fā)出跨域HTTP請求。出于安全原因,瀏覽器限制從腳本內發(fā)起的跨源HTTP請求。例如,XMLHttpRequest并且遵循同源策略。因此,使用XMLHttpRequest提取 的Web應用程序只能向自己的域發(fā)出HTTP請求。

什么是同源策略

同源策略是一種關鍵的安全機制,它限制從一個源加載的文檔或腳本如何與來自另一個源的資源交互。

瀏覽器禁止接收信息的目的是為了防止惡意網(wǎng)站從其他網(wǎng)站讀取機密信息,但也阻止網(wǎng)站內容合法讀取其他網(wǎng)站提供的信息。

同源是指"協(xié)議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。

舉例對比:

http://hotel.jd.com/dir/index.html

url 是否同源 說明
http://hotel.jd.com/dir2/pages.html 同源 僅鏈接不同
http://hotel.jd.com/dir/pages/index.html 同源 僅鏈接不同
https://hotel.jd.com/index.html 不同源 協(xié)議不同
http://hotel.jd.com:81/pages/index.html 不同源(IE同源) 端口不同
http://train.jd.com/pages/index.html 不同源 子域名不同
http://baidu.com 不同源 主域名不同

【注】IE不包括端口到同源檢查。因此,https://company.com:81/index.htmlhttps://company.com/index.html被認為是同源的,沒有任何限制。這些異常是非標準的,在任何其他瀏覽器中都不受支持。

瀏覽器可以鏈接跨域資源的html元素:

img、script、css、video、audio、object、embed、applet、@font-face、frame、iframe等。

(1)<img src=""></img>

(2)undefinedundefinedundefined<script src=""></script>標簽嵌入跨域腳本。語法錯誤信息只能在同源腳本中捕捉到。jsonp也用到了。

(3) <link src="">標簽嵌入CSS。由于CSS的松散的語法規(guī)則,CSS的跨域需要一個設置正確的Content-Type消息頭。不同瀏覽器有不同的限制: IE, Firefox, Chrome, Safari (跳至CVE-2010-0051)部分 和 Opera。

(4)<video> 和 <audio>嵌入多媒體資源。

(5)<object>, <embed> 和 <applet>的插件。

(6)@font-face引入的字體。一些瀏覽器允許跨域字體( cross-origin fonts),一些需要同源字體(same-origin fonts)。

(7) <frame> 和 <iframe>載入的任何資源。站點可以使用X-Frame-Options消息頭來阻止這種形式的跨域交互。

常見的跨域

接口

main.js:1 Mixed Content: The page at 'https://hotelm-yf.jd.com/coupon' was loaded over HTTPS, but requested an insecure resource 'http://hotel.m.jd.com/api/json/login'. This request has been blocked; the content must be served over HTTPS.

coupon:1 Access to fetch at 'https://hotelm-yf.jd.com/api/wechat/getActivityHotelList' from origin 'http://hotelm-yf.jd.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

[圖片上傳失敗...(image-f3a708-1566981016996)]

[圖片上傳失敗...(image-42aac-1566981016996)]

HTTPS和http跨域提示

[圖片上傳失敗...(image-9c5aa5-1566981016996)]

僅設置了http://hotel.m.jd.comhttps://hotel.m.jd.com時會出現(xiàn)的錯誤

[圖片上傳失敗...(image-92cc48-1566981016996)]

圖片

[圖片上傳失敗...(image-b662f6-1566981016996)]

圖片

?

No 'Access-Control-Allow-Origin' header is present on the requested resource. Originis therefore not allowed access

?

圖片防盜鏈

會檢測訪問圖片的referer

<meta name="referrer" content="no-referrer" /> 解決

GET https://csdnimg.cn/pubfooter/images/job-QR.png 403

[圖片上傳失敗...(image-51502b-1566981016996)]

  1. 跨站請求正常發(fā)起,netWork上可以正常查看,但是結果被瀏覽器攔截了。

    跨域的iframe

    iframe跨域時僅支持以下JS的api調用

    方法
    window.blur
    window.close
    window.focus
    window.postMessage
    location.replace
    屬性
    window.closed 只讀
    window.frames 只讀
    window.length 只讀
    window.location 讀/寫.
    window.opener 只讀
    window.parent 只讀
    window.self 只讀
    window.top 只讀
    window.window 只讀

如何阻止跨域

跨域數(shù)據(jù)存儲

瀏覽器中存儲的數(shù)據(jù)(如localStorage和IndexedDB)的訪問按源分開。每個源都有自己的獨立存儲,一個源中的JavaScript不能從屬于另一個源的存儲讀寫。

cookie使用一個單獨的起源定義。頁面可以為自己的域或任何父域設置cookie,只要父域不是公共后綴。Firefox和Chrome使用公共后綴列表來確定域是否是公共后綴。Internet Explorer使用自己的內部方法來確定域是否是公共后綴。無論使用哪種協(xié)議(HTTP/HTTPS)或端口,瀏覽器都將使cookie對給定域(包括任何子域)可用。設置cookie時,可以使用域、路徑、安全和僅http標志限制其可用性。當您讀取cookie時,您無法看到它是從何處設置的。即使您只使用安全的https連接,您看到的任何cookie都可能是使用不安全連接設置的。

二、跨域解決的方式

1.跨域資源共享(CORS)

CORS是一個W3C標準,全稱是跨域資源共享(Cross-origin resource sharing)。它允許瀏覽器向跨域服務器,發(fā)出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。

瀏覽器限制從腳本內發(fā)起的跨域HTTP請求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 這意味著使用這些API的Web應用程序只能從加載應用程序的同一個域請求HTTP資源,除非響應報文包含了正確CORS響應頭。

跨域資源共享(CORS)機制為Web服務器提供跨域訪問控制,從而實現(xiàn)安全的跨域數(shù)據(jù)傳輸?,F(xiàn)代瀏覽器在API容器中使用CORS(例如XMLHttpRequestFetch)來緩解跨域HTTP請求的風險。

Access-Control-Allow-Origin

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n143" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Access-Control-Allow-Origin: *</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n144" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">服務器默認是不被允許跨域的。配置Access-Control-Allow-Origin *后,表示服務器可以接受所有的請求源(Origin),即接受所有跨域的請求。</pre>

為了保障系統(tǒng)的安全性,不建議設置為通配 * 。并且這種方式瀏覽器不能攜帶cookie信息(攜帶cookie信息只能使用真實域)。

Access-Control-Allow-Origin也可指定對應的域名,單個或多個,:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n147" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Access-Control-Allow-Origin: http://test.blyoo.com,https://www.blyoo.com</pre>

Access-Control-Allow-Credentials

響應報頭指示的請求的響應是否可以暴露于該頁面。當true值返回時它可以被暴露。

Credentials的憑證是 Cookie ,授權標頭或 TLS 客戶端證書。

當作為對預檢請求的響應的一部分使用時,它指示是否可以使用憑證進行實際請求。請注意,簡單的GET請求不是預檢的,所以如果請求使用憑證的資源,如果此資源不與資源一起返回,瀏覽器將忽略該響應,并且不會返回到 Web 內容。

Access-Control-Allow-Credentials的 header 文件與該XMLHttpRequest.withCredentials屬性或者在提取 API credentialsRequest()構造函數(shù)中的選項一起工作。必須在雙方(Access-Control-Allow-Credentials的 header 和 XHR 或 Fetch 請求中)設置證書,以使 CORS 請求憑證成功

需要注意的是,在帶憑據(jù)請求中, Access-Control-Allow-Origin: 頭不能是通配符 "*",必須是一個有效的域名。

2.服務端配置:

1.Nginx服務器配置cors

Nginx的配置文件中配置以下參數(shù)

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n157" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">add_header Access-Control-Allow-Origin *;</pre>

多個指定域名:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n159" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">add_header Access-Control-Allow-Origin http://test.blyoo.com,https://www.blyoo.com;</pre>

The ‘Access-Control-Allow-Origin’ header contains multiple values, but only one is allowed

The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

代碼中查看是不是配置:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n163" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">header("Access-Control-Allow-Origin: *");</pre>

nginx配置有沒有配置:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n165" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">add_header Access-Control-Allow-Origin *;</pre>

這兩個配置,只要保留一個即可。

列表配置參考

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n168" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">map http_origincorsHost {
default 0;
"~http://www.example.com" http://www.example.com;
"~http://m.example.com" http://m.example.com;
"~http://wap.example.com" http://wap.example.com;
}

server
{
listen 80;
server_name www.example2.com;
root /usr/share/nginx/html;
location /
{
add_header Access-Control-Allow-Origin $corsHost;
}
}</pre>

其它配置參考:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n170" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
?
if ($request_method = 'OPTIONS') {
return 204;
}
} </pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n172" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">if (http_origin ~* "^http://hotelm-yf.jd.com"){
set cors_originhttp_origin;
}
if (http_origin ~* "^https://hotelm-yf.jd.com"){
set cors_originhttp_origin;
}
if (http_origin ~* "^https://hotel.m.jd.com"){
set cors_originhttp_origin;
}
if (http_origin ~* "^http://hotel.m.jd.com"){
set cors_originhttp_origin;
}
add_header 'Access-Control-Allow-Origin' $cors_origin;</pre>

2.JAVA中配置cors

如果服務端是Java開發(fā)的,添加如下設置允許跨域即可,但是這樣做是允許所有域名都可以訪問,不夠安全。并且這種方式瀏覽器不能攜帶cookie信息(攜帶cookie信息只能使用真實域)。這種方式只推薦在不帶cookie信息的開發(fā)中測試使用。代碼如下:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n177" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">response.setHeader("Access-Control-Allow-Origin","*");</pre>

為保證安全性,可以只添加部分域名允許訪問,添加位置可以在下面三處任選一個。

(1)可以在過濾器的filter的dofilter()方法種設置。

(2)可以在servlet的get或者post方法里面設置。

(3)可以放在訪問的jsp頁面第一行。

使用dofilter()的Demo

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" contenteditable="true" cid="n183" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {
// 將ServletResponse轉換為HttpServletResponse
HttpServletResponse httpResponse = (HttpServletResponse) res;
// 如果不是80端口,需要將端口加上,如果是集群,則用Nginx的地址,同理不是80端口要加上端口
String [] allowDomain= {"http://www.baidu.com","http://123.456.789.10","http://123.16.12.23:8080"};
Set allowedOrigins= new HashSet(Arrays.asList(allowDomain));
String originHeader=((HttpServletRequest) req).getHeader("Origin");
if (allowedOrigins.contains(originHeader)){
httpResponse.setHeader("Access-Control-Allow-Origin", originHeader);
httpResponse.setContentType("application/json;charset=UTF-8");
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token");
// 如果要把Cookie發(fā)到服務器,需要指定Access-Control-Allow-Credentials字段為true
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Access-Control-Expose-Headers", "*");
}
chain.doFilter(req, res);
} </pre>

3.PHP配置cors

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="php" contenteditable="true" cid="n185" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//如果需要設置允許所有域名發(fā)起的跨域請求,可以使用通配符 *
<?php
header("Access-Control-Allow-Origin: *");
?>

//單個
<?php
header("Access-Control-Allow-Origin: www.xxx.xom");
?>

//多個
<?php
origin = 'https://www.google.com,https://www.baidu.com'; header('Access-Control-Allow-Origin:' .origin);
?>

//多個
<?php
allowed_origins = array( "http://www.aaa.com" , "http://app.bbb.com" , "http://cms.ccc.com" , ); if (in_array(_SERVER['HTTP_ORIGIN'], allowed_origins)){ @header("Access-Control-Allow-Origin: " ._SERVER['HTTP_ORIGIN']);
}
?></pre>

4.apache配置cors

在httpd配置或.htaccess文件中添加如下語句

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n188" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">SetEnvIf Origin "^(.*.example.com)" ORIGIN_SUB_DOMAIN=1
Header set Access-Control-Allow-Origin "%{ORIGIN_SUB_DOMAIN}e" env=ORIGIN_SUB_DOMAIN</pre>

或apache下修改vhosts中根域名的配置:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="php" contenteditable="true" cid="n190" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><Directory "/Users/cindy/dev">
AllowOverride ALL
Header set Access-Control-Allow-Origin https://www.google.com,https://www.baidu.com
</Directory></pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n191" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><VirtualHost *:80>
Header add Access-Control-Allow-Origin *
Header add Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header add Access-Control-Allow-Headers "Content-Type"
<Directory myhtdocsdir>
AllowOverride All
</Directory>
</VirtualHost></pre>

3.前端配置

如僅需要獲取接口返回數(shù)據(jù),服務端配置好 Access-Control-Allow-Origin 前端即可獲取到后端返回的數(shù)據(jù)了。當跨域還需要傳遞憑證cookie時。需要在請求時配置Credentials為true。

配置Credentials

以下是前端用各種方式請求時設置Credentials的方式。

1.XHR設置credetials

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" contenteditable="true" cid="n197" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);</pre>

2.Fetch設置攜帶credentials

默認情況下,fetch 不會從服務端發(fā)送或接收任何 cookies, 如果站點依賴于用戶 session,則會導致未經(jīng)認證的請求(要發(fā)送 cookies,必須設置 credentials 選項)

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" contenteditable="true" cid="n200" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">fetch(url, {
credentials: 'include'
})</pre>

cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached ? credentials: 'same-origin', // include, same-origin, *omit

參考文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

3.axios設置credentials

設置axios.defaults.withCredentials

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n205" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import axios from 'axios'
axios.defaults.withCredentials = true</pre>

單獨設置

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n207" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">axios({
method: 'get',
url: 'XXX',
withCredentials: true
})</pre>

4.vue-resource設置credentials

以下為全局引用vue的demo。非全局引用的參考參數(shù)傳遞。原理一致

VUE官方推薦使用axios ,vue-resource不更新了

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n211" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import vue from 'vue'
vue.http.get(url,{
credentials: true
},{
emulateJSON: true
})
?</pre>

  1. 一定要設置 {emulateJSON: true},不然跨域不成功.
5.jQuery ajax設置credentials

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" contenteditable="true" cid="n216" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">$.ajax({
url : 'http://hotel.m.jd.com/api/login',
data : data,
dataType: 'json',
type : 'POST',
xhrFields: {
withCredentials: true
},
crossDomain: true,
contentType: "application/json",
?</pre>

四、前端調試跨域

webpack配置接口地址代理

啟動服務器后,本地開發(fā)服務下 http://localhost:8080 ,接口地址是 http://www.xxx.com/api/,就會存在跨域的請求,導致接口請求不成功。

webpack自帶代理功能,通過以下配置??梢詫⒔涌诘刂反淼姆绞接成涞奖镜?。

解決開發(fā)環(huán)境的跨域問題(不用在去配置nginx和host)

在webpack.config.js中配置

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n224" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">?</pre>

webpack代理參考:https://webpack.js.org/configuration/dev-server/#devserver-proxy

whistle修改請求頭解決跨域

No 'Access-Control-Allow-Origin' header is present on the requested resource

2.jsonp

3.doucument.domain

用document.domain來指定域,主要解決的是子域與父域之間的跨域。

如: hotel.m.jd.com、train.m.jd.com 指定到m.jd.com

4.postMessage()

postMessage()允許來自不同源的腳本采用異步方式進行通信,可以實現(xiàn)跨域消息傳遞。 postMessage(data,origin) data:要傳遞的數(shù)據(jù) origin:指明目標窗口的源。協(xié)議主機端口號 接收消息:監(jiān)聽window的message事件,包括 data——傳遞過來的message source——發(fā)送消息的窗口對象 origin——發(fā)送消息窗口的源

5.location.hash

6.script篇

7.window.name

window.name 傳輸技術,原本是 Thomas Frank 用于解決 cookie 的一些劣勢(每個域名 4 x 20 Kb的限制、數(shù)據(jù)只能是字符串、設置和獲取 cookie 語法的復雜等等)而發(fā)明的。后來 Kris Zyp 在此方法的基礎上強化了 window.name 傳輸 ,用來解決跨域數(shù)據(jù)傳輸問題。

window.name 的美妙之處:name值在不同的頁面(甚至不同域名)加載后依舊存在,并且可以支持非常長的 name 值(2MB)

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n242" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">在A域名下設置window.name,通過href跳轉至目標頁。 再獲取window.name的參數(shù)
例:
A頁面
window.name = '跨域的參數(shù)'
<a id="al" >點擊我跨域傳值</a>
B頁面
window.name //跨域的參數(shù)
?</pre>

參考文獻

  1. 同源策略https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

    https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy

  2. HTTP訪問控制(CORS)https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

  3. Server-Side Access Controlhttps://developer.mozilla.org/zh-CN/docs/Web/HTTP/Server-Side_Access_Control

  4. XY博客https://www.cnblogs.com/sunmmi/articles/5956554.html

  5. Fetch https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

  6. webpack proxy:https://webpack.js.org/configuration/dev-server/#devserver-proxy

crossorigin = "anonymous"

七種跨域方法【2.document.domain篇】

??

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 什么是跨域 跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實...
    Yaoxue9閱讀 1,412評論 0 6
  • 什么是跨域 跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實...
    他方l閱讀 1,134評論 0 2
  • 什么是跨域 跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實...
    HeroXin閱讀 955評論 0 4
  • 歡迎關注微信公眾號:全棧工廠 本文主要參考跨域資源共享 CORS 詳解[http://www.ruanyifeng...
    liqingbiubiu閱讀 2,043評論 0 3
  • 題目1.什么是同源策略? 同源策略(Same origin Policy): 瀏覽器出于安全方面的考慮,只允許與本...
    FLYSASA閱讀 1,876評論 0 6

友情鏈接更多精彩內容