預(yù)備知識:
- 只有瀏覽器才會有跨域請求限制涩赢,也就是如果是服務(wù)器之間直接發(fā)起http請求不會存在該限制湃窍。
- CORS是在不滿足同源策略的情況下辙售,才有可能引起跨域請求限制材失。
- 同源策略校驗包括protocol + host/domain + port(80/443會省略),只有三者完全相同是瘸恼,才滿足同源策略愁拭。
- <script><img><iframe><link><video><audio>帶有src屬性褪贵,瀏覽器允許跨域請求
- 表單提交时捌、重定向允許跨域?qū)懖僮鳎ù藭r可能引起CSRF怒医,可以通過埋token的方式避免)
- 瀏覽器不支持跨站點(diǎn)訪問Cookie、LocalStorage匣椰、IndexDB
- 瀏覽器不支持跨站點(diǎn)訪問DOM
- 瀏覽器不支持跨站點(diǎn)的AJAX請求裆熙,在不進(jìn)行跨域請求配置的情況下。
跨域請求的解決方案:
-
簡單請求
- 請求method只能是GET/POST/HEAD
- 僅能使用CORS安全的Header: Accept禽笑、Accept-Language入录、Content-Language、Content-Type
- Content-Tytpe只能是如下的一種:text/plain佳镜、multipart/form-data僚稿、applicaton/x-www-form-urlencoded
- 請求中必須攜帶Origin頭部,服務(wù)端通過響應(yīng)Access-Control-Allow-Origin頭部來只是瀏覽器該如何處理該請求(如果Access-Control-Allow-Origin為Origin的值或者為*時蟀伸,瀏覽器才允許渲染請求結(jié)果)
復(fù)雜請求
請求示例:
- 創(chuàng)建html文件蚀同,內(nèi)部含有Ajax請求(http://127.0.0.1:8081和http://127.0.0.1:8082不滿足同源策略)
<html>
<body>
<p>跨域請求測試</p>
<p id="resp"></p>
<script>
var invocation = new XMLHttpRequest();
var url = "http://127.0.0.1:8082";
function handler() {
if (invocation.readyState == 4) {
if (invocation.status==200) {
console.log(invocation.responseText);
document.getElementById('resp').innerHTML=invocation.responseText;
}
}
}
function callOtherDomain() {
if (invocation) {
invocation.open('GET', url, true);
invocation.onreadystatechange = handler;
invocation.send();
}
}
callOtherDomain();
</script>
</body>
</html>%
```html
2. 配置nginx server
server {
listen 8081;
server_name localhost;
charset utf-8;
location / {
# 這個地方需要修改成你上面保存的cors.html的目錄
root /path-to-directory;
index cors.html cors.htm;
}
}
server {
listen 8082;
server_name localhost;
charset utf-8;
location / {
return 200 'hello world';
}
}
保存,執(zhí)行nginx -s reload
-
打開瀏覽器啊掏,訪問http://127.0.0.1:8081蠢络。你將會發(fā)現(xiàn)http://127.0.0.1:8082的Ajax請求失敗了,瀏覽器提示CORS error(MissingAllowOriginHeader) 迟蜜。
但是通過抓包可以看到刹孔,nginx其實將相應(yīng)('hello world')返回給瀏覽器了,但是由于不滿足CORS policy,相應(yīng)被瀏覽器隱藏了娜睛。抓包截圖:
image.png
3.1 修改8082站點(diǎn)的配置髓霞,以允許來自8081的跨站請求
server {
listen 8082;
server_name localhost;
charset utf-8;
location / {
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
return 200 'hello world';
}
}
再次刷新瀏覽器,可以發(fā)現(xiàn)請求正常返回了
因為Response header中返回了Access-Control-Allow-Origin: http://127.0.0.1:8081
4. 更多的跨域請求響應(yīng)Header
5. 常見錯誤
5.1 MultipleAllowOriginValues
Access to XMLHttpRequest at 'http://127.0.0.1:8082/' from origin 'http://127.0.0.1:8081' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://127.0.0.1:8081, http://127.0.0.1:8083', but only one is allowed.
原因:response header中返回了多個AccessControlAllowOrigin值(可以是相同的畦戒,也可以是不同的)方库。例如如下的服務(wù)端返回:
server {
listen 8082;
server_name localhost;
charset utf-8;
location / {
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
return 200 'hello world';
}
}
Access-Control-Allow-Origin只能返回一個源
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8083';
這種不同的源也是不行的,即使相同的源也是不行的。
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081,http://127.0.0.1:8083';
這種也是不行的