整理中
目標:
了解跨域
解決跨域
服務器配置跨域(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.html和https://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.com 用https://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)]
-
跨站請求正常發(fā)起,netWork上可以正常查看,但是結果被瀏覽器攔截了。
跨域的iframe
iframe跨域時僅支持以下JS的api調用
方法 window.blurwindow.closewindow.focuswindow.postMessagelocation.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(例如XMLHttpRequest或Fetch)來緩解跨域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 credentials的Request()構造函數(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 corsHost {
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 ("){
set http_origin;
}
if ("){
set http_origin;
}
if ("){
set http_origin;
}
if ("){
set http_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);
?>
//多個
<?php
_SERVER['HTTP_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)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>
- 一定要設置 {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>
參考文獻
-
同源策略https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy
HTTP訪問控制(CORS)https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
Server-Side Access Controlhttps://developer.mozilla.org/zh-CN/docs/Web/HTTP/Server-Side_Access_Control
Fetch https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
webpack proxy:https://webpack.js.org/configuration/dev-server/#devserver-proxy
crossorigin = "anonymous"
??