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: 1728000Node.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>; } } }