浏览器会有同源策略,域名,协议,端口只要有一个不一样就是跨域.javascript
同源策略只限制浏览器端,跨域请求是能够发去的,可是请求响应response被浏览器堵塞了,是限制了不一样源的读,但不限制不一样源的写,服务端没有同源策略这一限制,form表单能够跨域发送信息也是这个缘由。html
限制:前端
(1) Cookie、LocalStorage 和 IndexDB 没法读取。vue
(2) DOM 没法得到。html5
(3) AJAX 请求不能发送java
浏览器某些静态文件加载标签不受同源策略限制:<script>< link>< img><video><audio><iframe>git
// 前端页面
<script>
function writeDate(_date){
document.write(_date);
}
</script>
<script src="http://192.168.0.103:9000/getDate?callback=writeDate"></script>
// 服务端返回一个脚本,在这个脚本里面执行writeDate函数:
function getDate(response, callback){
response.writeHead(200, {"Content-Type": "text/javascript"});
var data = "2016-2-19";
response.end(callback + "('" + data + "')");
}
//jQuery
$.ajax({
url: 'http://192.168.0.103:9000/getDate',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "handleCallback", // 自定义回调函数名
data: {}
});
//Vue
this.$http.jsonp('http://192.168.0.103:9000/getDate', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
复制代码
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不一样源服务器上的指定的资源。 ----MDN(CORS)github
cors将跨域请求分为简单请求和非简单请求web
(1) 请求方法是如下三种方法之一:HEAD/GET/POSTajax
(2)HTTP的头信息不超出如下几种字段:Accept/Accept-Language/Content-Language/Last-Event-ID/
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
实现方法
服务端在http响应头中添加Access-Control-Allow-origin
“*”表示任何源均可以访问,也能够指定能够访问的源
必须首先使用 OPTIONS
方法发起一个预检请求到服务器,返回码是204,预检测经过才会真正发出请求,这才返回200。
触发非简单请求的条件
window.postMessage(message,targetOrigin) 方法是html5新引进的特性,不受同源策略限制。
用于解决如下方面的问题: a.) 页面和其打开的新窗口的数据传递 b.) 多窗口之间消息传递 c.) 页面与嵌套的iframe消息传递 d.) 上面三个场景的跨域数据传递
目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
// postMessage
// 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
Bwindow.postMessage('data', 'http://B.com');
// 在窗口B中监听
Awindow.addEventListener('message', function (event) {
console.log(event.origin); // 发送源,接受谁
console.log(event.source); // Awindow的引用
console.log(event.data);
}, false);
复制代码
安全问题
hash为url#后的内容,hash改变页面不刷新, 故而能够实现跨域通讯
?后的search内容 ,也叫query 改变页面刷新,不能作跨域通讯
// 利用hash,场景是当前页面 A 经过iframe或frame嵌入了跨域的页面 B
// 在A中伪代码以下:
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'data';
// 在B中的伪代码以下
window.onhashchange = function () {
var data = window.location.hash;
};
复制代码
www.ruanyifeng.com/blog/2017/0…
HTTP 协议有一个缺陷:通讯只能由客户端发起,作不到服务器主动向客户端推送信息。若是服务器有连续的状态变化,客户端要获知就很是麻烦。咱们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。
WebSocket 最大特色就是,服务器能够主动向客户端推送信息,客户端也能够主动向服务器发送信息
var ws = new WebSocket('wss://echo.websocket.org');
// 发送
ws.onopen = function (evt) {
console.log('Connection open ...');
ws.send('Hello WebSockets!');
};
// 接受
ws.onmessage = function (evt) {
console.log('Received Message: ', evt.data);
ws.close();
};
// 关闭
ws.onclose = function (evt) {
console.log('Connection closed.');
};
复制代码
若是你的前端应用和后端 API 服务器没有运行在同一个主机上,你须要在开发环境下将 API 请求代理到 API 服务器。这个问题能够经过 vue.config.js
中的 devServer.proxy
选项来配置。
devServer.proxy
能够是一个指向开发环境 API 服务器的字符串:
module.exports = {
devServer: {
proxy: 'http://localhost:4000'
}
}
复制代码
这会告诉开发服务器将任何未知请求 (没有匹配到静态文件的请求) 代理到http://localhost:4000
。
若是你想要更多的代理控制行为,也可使用一个 path: options
成对的对象。完整的选项能够查阅 http-proxy-middleware 。
module.exports = {
devServer: {
proxy: {
'/api': {
target: '<url>',
ws: true,
changeOrigin: true
},
'/foo': {
target: '<other_url>'
}
}
}
}
复制代码
参考: