您的位置:

浏览器同源策略详解

一、同源定义

同源即指两个URL协议,域名和端口号都相同,这样才可以互相访问彼此的资源。如果两个URL不满足以上条件,那么就是跨域请求。

例如:a.com和b.com之间的请求就是跨域请求,但是a.com和a.com:8080之间的请求就是同源请求。

二、同源策略的作用

浏览器的同源策略是为了防止恶意的网站窃取用户的隐私信息而设计的。如果没有同源策略,那么一个网页可以通过一些恶意的脚本来获取另一个网页中用户的敏感信息,例如Cookie。

同源策略可以保护用户的隐私信息,但也会限制网站与外部资源的交互,这就需要设计跨域解决方案。

三、同源策略的限制

1、Cookie、LocalStorage和IndexedDB无法读取。同源A网页下,无法读取同源B网页的Cookie、LocalStorage和IndexedDB。

<script>
let cookie = document.cookie; // 无法获得
let localStorage = window.localStorage; // 无法获得
let indexedDB = window.indexedDB; // 无法获得
</script>

2、DOM无法获取。同源A网页无法获取同源B网页中的DOM元素。

<iframe src="http://b.com"></iframe>
<script>
let iframe = document.getElementsByTagName('iframe')[0];
let bDom = iframe.contentWindow.document.getElementsByTagName('body')[0]; // 无法获得
</script>

3、AJAX请求无法发送。同源A网页无法向同源B网页发送AJAX请求。

fetch('http://b.com', {
  method: 'get'  // 无法请求
})

四、跨域解决方案

1、JSONP

JSONP利用script标签不存在跨域限制的特性,可以通过动态创建script标签,向另一个服务器请求数据,将响应结果放到回调函数中返回到网页中。

<script>
function handleData(res) {
  console.log(res);
}
let script = document.createElement('script');
script.src = "http://b.com/api?callback=handleData"; // 动态创建script标签
document.head.appendChild(script);
</script>

2、CORS

CORS实现了前后端的协商机制,由后端设置Access-Control-Allow-Origin响应头来允许跨域请求。

具体地,当浏览器发现请求不符合同源策略时,会进行一次CORS预检请求,即向另一个服务器发起OPTIONS请求,询问是否允许跨域,如果得到响应,则可以进行跨域请求。

后端需要设置Access-Control-Allow-Origin、Access-Control-Allow-Credentials等响应头,前端需要在AJAX请求中加上withCredentials和设置xhr的请求头。

// 后端设置响应头
Access-Control-Allow-Origin: http://a.com
Access-Control-Allow-Credentials: true

// 前端AJAX请求
let xhr = new XMLHttpRequest();
xhr.withCredentials = true; // 允许跨域带Cookie
xhr.open("GET", "http://b.com/api");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();

3、WebSocket

WebSocket是一种可以在单个TCP连接上进行全双工通信的网络协议,在进行跨域通信时,WebSocket可以直接连接到另一个服务器并发送数据,不再需要通过CORS等方式解决跨域问题。

let socket = new WebSocket('ws://b.com');
socket.onopen = function() {
  socket.send('hello, b');
}
socket.onmessage = function(event) {
  console.log(event.data);
}

五、小结

浏览器的同源策略可以保护用户的隐私信息,但也会限制网站与外部资源的交互,需要设计跨域解决方案。常用的跨域解决方案有JSONP、CORS、WebSocket等。在使用跨域解决方案时,需要注意安全性和对浏览器的性能影响。