1. 同源策略
如果兩個(gè)頁面的協(xié)議结榄,端口和域名都相同杖虾,則兩個(gè)頁面具有相同的源(origin)流昏。
The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin.
同源策略是一種安全機(jī)制冀偶,它限制了非同源腳本之間的交互方式。
例如淮椰,在使用XMLHttpRequest
或 <img>
標(biāo)簽時(shí)五慈,會(huì)受到同源策略的約束纳寂。
這些交互通常分為三類:
(1)通常允許跨域?qū)懖僮鳎–ross-origin writes)主穗。例如鏈接(links),重定向以及表單提交毙芜。
(2)通常允許跨域資源嵌入(Cross-origin embedding)忽媒。
(3)通常不允許跨域讀操作(Cross-origin reads)。但骋钢啵可以通過內(nèi)嵌資源來巧妙的進(jìn)行讀取訪問晦雨。
例如,可以讀取嵌入圖片的高度和寬度隘冲,調(diào)用內(nèi)嵌腳本的方法闹瞧,或 availability of an embedded resource。
以下是可能嵌入跨域的資源的一些示例:
(1)<script src="..."></script>
標(biāo)簽嵌入跨域腳本展辞。語法錯(cuò)誤信息只能在同源腳本中捕捉到奥邮。
(2)<link rel="stylesheet" href="...">
標(biāo)簽嵌入CSS。
(3)<img>
嵌入圖片。支持的圖片格式包括PNG,JPEG,GIF,BMP,SVG,...
(4)<video>
和 <audio>
嵌入多媒體資源洽腺。
(5)<object>
, <embed>
和 <applet>
的插件脚粟。
(6)@font-face
引入的字體。一些瀏覽器允許跨域字體( cross-origin fonts)蘸朋,一些需要同源字體(same-origin fonts)核无。
(7)<frame>
和 <iframe>
載入的任何資源。站點(diǎn)可以使用X-Frame-Options
消息頭來阻止這種形式的跨域交互藕坯。
2. 跨域資源共享
跨域資源共享 Cross-Origin Resource Sharing (CORS)团南,通過在服務(wù)器端設(shè)置 Access-Control-Allow-Origin 響應(yīng)頭,
允許瀏覽器發(fā)起跨域請(qǐng)求炼彪,例如已慢,跨域 XMLHttpRequest,Fetch 請(qǐng)求霹购。
Access-Control-Allow-Origin 的值為發(fā)起跨域請(qǐng)求的那個(gè)域名佑惠,表示允許這個(gè)域名的網(wǎng)頁訪問當(dāng)前資源。
服務(wù)器端可以通過請(qǐng)求頭中的 Origin 字段齐疙,來判斷某個(gè)請(qǐng)求是否跨域請(qǐng)求膜楷。
3. onerror信息
服務(wù)器端如果沒有設(shè)置 CORS,
普通的跨域<script>
標(biāo)簽贞奋,將只向window.onerror
反饋盡量少的內(nèi)容赌厅。
window.onerror = (...args) => console.log(args); // ["Script error.", "", 0, 0, null]
給<script>
標(biāo)簽添加 crossorigin 屬性,
并在服務(wù)器端設(shè)置 Access-Control-Allow-Origin 響應(yīng)頭轿塔,允許腳本被跨域訪問特愿,
就可以在window.onerror
中獲取更詳細(xì)的日志信息。
[
"Uncaught ReferenceError: a is not defined",
"http://127.0.0.1:8081/index.js",
1,
1,
ReferenceError: a is not defined
at http://127.0.0.1:8081/index.js:1:1]
注:
普通<script>
標(biāo)簽是可以加載跨域腳本的勾缭,
但如果給跨域<script>
標(biāo)簽添加了crossorigin
屬性揍障,
(且服務(wù)器端沒有設(shè)置Access-Control-Allow-Origin 響應(yīng)頭),
就會(huì)出現(xiàn)以下錯(cuò)誤俩由,
Access to Script at 'http://127.0.0.1:8081/index.js' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://127.0.0.1:8080' is therefore not allowed access.
示例代碼:
(1)在./test-cors1/ 文件夾下啟動(dòng)靜態(tài)網(wǎng)站毒嫡,監(jiān)聽8080端口
<!-- ./test-cors1/index.html -->
<script crossorigin src="http://127.0.0.1:8081/index.js"></script>
(2)在./test-cors2/ 文件夾下啟動(dòng)靜態(tài)網(wǎng)站,監(jiān)聽8081端口
// ./test-cors2/index.js
a;
4. crossorigin屬性
crossorigin 屬性不止可以用于<script>
標(biāo)簽幻梯,還可以用與<img>
兜畸,<video>
等標(biāo)簽,
用于配置 CORS 的請(qǐng)求數(shù)據(jù)碘梢,見下表咬摇,
Keyword | State | Request Mode | Credentials Mode |
---|---|---|---|
the attribute is omitted | No CORS | "no-cors" | "omit" |
"" | Anonymous | "cors" | "same-origin" |
"anonymous" | Anonymous | "cors" | "same-origin" |
"use-credentials" | Use Credentials | "cors" | "include" |
不同的crossorigin
值,指定了不同的Request Mode 和 Credentials Mode煞躬。
其中肛鹏,術(shù)語use credentials指的是,cookies,http authentication 和客戶端ssl證書龄坪。
The term user credentials for the purposes of this specification means cookies, HTTP authentication, and client-side SSL certificates that would be sent based on the user agent's previous interactions with the origin. Specifically it does not refer to proxy authentication or the Origin header.
參考
MDN: Same-origin policy
MDN: Cross-Origin Resource Sharing (CORS)
MDN: script - crossorigin
MDN: The crossOrigin attribute
W3C HTML5: CORS settings attributes
W3C: CORS
Wikipedia: Cross-origin resource sharing