什么是同源策略及限制
- 同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
- 同源策略是由
Netscape
提出的一个著名的安全策略
- 什么是源呢? 一个源包含三部分内容,协议,域名,端口号。所谓同源指的就是,
协议
,域名
,端口号
相同。 - 限制是什么意思呢? 不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,主要限制的几个方面如下:
Cookie、LocalStorage 和 IndexDB无法读取
DOM无法获得
AJAX请求不能发送,它只适合同源的通信,跨域它就不合适了
前后端如何通信
常用的三种方式:
- Ajax 它是同源下的通信方式
- WebSocket 它不受同源策略的限制
- CORS 支持跨域通信,也支持同源通信
如何创建AJAX
在写的过程中,面试官主要考察的几个点是下边几个部分:
- XMLHttpRequest对象的工作流程
- 兼容性处理
- 事件的触发条件
- 事件的触发顺序
Ajax请求的五个步骤
- 创建 XMLHttpRequest 异步对象
- 设置请求的方式和地址
- 接着用send发送请求
- 监听状态变化
- 接收返回的数据
下边是封装后的Ajax请求
function ajax(opts){
var type = opts.type || 'GET'
var url = opts.url
var dataType = opts.dataType || 'json'
var data = opts.data || {}
var onsuccess = opts.onsuccess || function(){}
var onerror = opts.onerror || function(){}
var dataStr = [];
for(var key in data){
dataStr.push(key+'='+data[key])
}
dataStr = dataStr.join('&')
if(type === 'GET'){
url += '?'+dataStr
}
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject()
xhr.open(type,url,true);
if(type === 'POST'){
xhr.send(data)
}else{
xhr.send()
}
xhr.onload = function(){
if((xhr.status >= 200 && xhr.status < 300)|| xhr.status === 304){
if(dataType === 'json'){
onsuccess(JSON.parse(xhr.responseText))
}else{
onsuccess(xhr.responseText)
}
}else {
onerror()
}
}
xhr.onerror = onerror
}
ajax({
url:'http://www.test.com/weather.php',
data:{
city:'杭州'
} ,
onsuccess:function(res){
console.log(res)
},
onerror:function(){
console.log('服务器异常')
}
})
跨域通信的几种方式
- JSONP
- JSONP(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
- 在出现postMessage和CORS之前,一直使用JSONP来跨域通信的。
- JSONP需要两个条件 script标签 和 后端的配合
- 总结:JSONP是通过 script标签加载数据的方式,去获取数据当做JS代码来执行,需要提前在页面上声明一个函数,函数名通过接口传参的方式传给后台,后台解析到函数名后,在原始数据的上包裹这个函数名,发送给前端,换句话说,JSONP需要对应接口的后端配合才可以实现
<div class="newBox">
<ul class="news"></ul>
<button class="show"> show News</button>
</div>
<script>
var btn = document.querySelector('.show');
var ulTag = document.querySelector('.news');
btn.onclick = function(){
var script = document.createElement('script');
script.src = 'http://www.test.com/getNews?callback=appendHtml'
document.head.appendChild(script);
document.head.removeChild(script)
}
function appendHtml(news){
var html = ''
news.forEach(item => {
html += '<li>'+item+'</li>'
})
ulTag.innerHTML = html
}
</script>
- Hash
场景是:当前页面A通过iframe嵌入了跨域的页面B
// 在A中,伪代码如下
var B = document.getElementByTagName('iframe');
B.src = B.src + '#' + 'data'
//在B中的伪代码如下
window.onhashchange = function(){
var data = window.location.hash
}
- postMessage
这个是HTML5新增的方法,该方法允许来自不同源的脚本采用异步方式进行有效的通信
// 窗口A(http://A.com) 向跨域的窗口B (http://B.com)发送消息,分为两个步骤
// 步骤一,发送消息,现在是A向B发送消息,所以,我们要获取到B窗口,注意是B窗口对象,调用postMessage
// postMessage方法第一个参数是要发送的数据,推荐使用字符串格式。第二个参数是接收方的源,可以是一个具体的源,也可以是一个*,不推荐写星号,它表示可以给任何窗口发送
Bwindow.postMessage('data','http://B.com')
//步骤二,在B窗口监听message事件,跟监听click事件一样
window.addEventLinstener('message',function(event){
console.log(event.origin) // 这里是发送消息的源 http://A.com
console.log(event.source) // 这里是哪个对象发送的消息 Awindow
console.log(event.data) // 这里是发送的消息 data
},false)
- WebSocket
// 声明一个WebSocket 对象,参数开头可以是ws或者wss,区别是是否加密,后边是指向服务器的地址
var ws = new WebSocket('wss://echo.websocket.org')
// 然后在onopen的时候发送消息
ws.onopen = function(evt){
console.log('Connection open...')
ws.send('Hello webSocket')
}
// 然后在onmessage接受对方给的消息
ws.onmessage = function(evt){
console.log('Received message'+evt.data)
ws.close()
}
// 最后,如果说不用这个通道了,关闭了这个通道,关闭的方法就是close方法,然后监听close事件
ws.onclose = function(evt){
console.log('Connection closed')
}
- CORS
CORS这个标准,是Ajax的一个变种,全称 "跨域资源共享" (cross-origin-resource-sharing),它允许浏览器向跨源服务器,发出
XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。
JSOP跨域 方法,有其不足之处,就是请求只能使用GET提交,如果传输的数据量比较大,那么这种方法就不行了
平时如果我们不借助框架,而是直接用js去写Ajax通信的话,一般需要用到XMLHttpRequest对象
在较新的标准中,我们可以借助fetch这个API,它就是用来实现CORS通信的。
它的第一个参数是地址,第二个参数是配置选项,之后就是成功的回调和捕获错误的回调
// 类似promise的用法
fetch('/test/url',{
method:'get'
}).then(function(response){
console.log(response
}).catch(function(error)){
console.log(error)
}
同源的通信,就像上边那样写就可以了,如果是跨域通信,需要在配置项里再加一些配置,具体加什么就不细说了,可以看资料
既然说CORS是Ajax的变种,那么CORS,为什么支持跨域通信呢?
当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:origin,后台会进行一系列的处理,如果确定接受请求,则在返回结果中,加入一个响应头 Access-Control-Allow-Origin:
浏览器判断该响应头中是否包含 origin的值,如果有,则浏览器会处理响应,我们就可以拿到数据,如果不包含浏览器就直接驳回,这时我们就无法拿到响应数据。
网友评论