1. 同源策略
所谓同源是指,域名
,协议
,端口
相同。浏览器在非同源时限制了以下三种行为:
Cookie
、LocalStorage
和IndexDB
的读取DOM
的获取AJAX
请求
2. 跨域问题
- 跨域只存在于浏览器端,不存在于
安卓
、ios
、Node.js
、python
、java
等其它环境 - 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了
3. Cookie、LocalStorage及DOM跨域访问
- 设置
document.domain
这种方法适用于两个网页一级域名相同,只是次级域名不同的情况。比如http://a.test.com/a.html
和http://b.test.com/b.html
,
只要在两个网页中设置相同的document.domain
,两个网页就可以共享Cookie
、LocalStorage
以及获取DOM
。document.domain = 'test.com';
window.postMessage()
window.postMessage()
是一个跨文档通信API,允许两个窗口进行通信而不受同源策略的限制。// 发送消息 targetWindow.postMessage(message, targetOrigin) // 接收消息 window.addEventListener("message", (event) => { // 消息来源域名过滤 if (event.origin !== "http://example.org:8080") return; // ... }, false);
4. AJAX 请求跨域
JSONP
借助于<script>
标签的src
属性,只能发GET
请求<!-- 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数 --> <script src="http://www.test.com/getData?callback=getData"></script> <!-- 处理服务器返回回调函数的数据 --> <script type="text/javascript"> // 服务器返回的数据会放到回调函数里面 function getData(res) { // 处理获得的数据 console.log(res.data) } </script>
CORS
CORS
(Cross-Origin Resource Sharing)是跨域资源共享的缩写。在服务端响应头中添加Access-Control-
相关字段,来允许跨域请求。// *表示允许任意源的访问,也可以指定特定的源 Access-Control-Allow-Origin:* // 表示跨域访问时带上cookie,需同时在ajax请求中设置`withCredentials: true`, Access-Control-Allow-Credentials: true // 允许的方法,多个方法以逗号分隔 Access-Control-Allow-Methods: GET, POST, PUT // 允许的头部,多个头部以逗号分隔 Access-Control-Allow-Headers:Content-Type // 允许浏览器在指定时间内,无需再发送预检请求进行协商,单位为秒 Access-Control-Max-Age: 1728000
Node.js
项目中可以直接使用cors
模块来快速实现。const express = require('express') // 引入cors模块,需要单独安装 const cors = require('cors') const app = express() app.use(cors())
WebSocket
WebSocket
是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信。WebSocket
和HTTP
都是应用层协议,都基于TCP
协议。但是WebSocket
是一种双向通信协议,在建立连接之后,WebSocket
的server
与client
都能主动向对方发送或接收数据。同时,WebSocket
在建立连接时需要借助HTTP
协议,取得响应后,建立的连接会从http
协议升级成WebSockets
协议,以支持双向通信。WebSockets
没有同源策略,因此可以跨域通信。const socket = new WebSocket("ws://www.example.com/socket"); // 必须是绝对路径 socket.send('hello'); // 服务端发送消息后,触发message事件 socket.onmessage = (event) => { console.log(event.data); };
5. Vue项目跨域开发
- 开发阶段
利用webpack-dev-server
来代理到要跨域的服务器上。
原理是:通过node
开一个服务器进行代理。前台发向后台服务器的请求,先发向node
所开的服务器,node
服务器以相同的参数向真正的服务器进行请求,再把响应返回给前台。//vue.config.js module.exports = { devServer: { proxy: { // 以'/api'开头的请求会被代理进行转发 '/api': { target: 'http://localhost:8081', // 目标服务器地址 changeOrigin: true } } } }
- 上线阶段
利用nginx
进行反向代理访问后端服务器。# nginx.conf http { server { listen 80; server_name <your_server_name>; root /data/www; location / { index index.html; } # 反向代理配置 location /api { proxy_pass <target_server>; } } }