跨域
协议、域名、端口不同,需要跨域
跨域解决方案
jsonp:JSON with Padding
<script>
标签没有同域限制- 服务端返回页面上 callback 包裹的 json 数据
- 兼容性好
- 仅支持 GET
CORS:Cross-origin resource sharing 跨域资源共享
简单请求 :
满足以下 2 条件
- GET HEAD POST
- Content-Type
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
复杂请求:
不满足以上2条件
-
需发送 OPTION 预检请求,查询服务器支持的方法
-
按请求类别处理
const express = require('express') const app = express() const whiteList = ['http://localhost'] app.use((req, res, next) => { const origin = req.headers.origin if (whiteList.includes(origin)) { // 允许访问源,附带凭证请求时,必须指定 URI。相反,可设置为 * res.setHeader('Access-Control-Allow-Origin', origin) // 允许请求头,逗号隔开 res.setHeader('Access-Control-Allow-Headers', 'authorization, username') // 允许请求方法,逗号隔开 res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, POST, OPTIONS') /* 允许凭证 客户端需配置 const xhr = new XMLHttpRequest() xhr.withCredentials = true */ res.setHeader('Access-Control-Allow-Credentials', true) // 预检请求的返回结果,允许请求头和请求方法可以被缓存多久,缓存期间不再发送预检请求,单位秒 res.setHeader('Access-Control-Allow-Max-Age', 10) // 允许响应头 res.setHeader('Access-Control-Expose-Headers', 'authorization, username') if (req.method === 'OPTIONS') { res.end() // 预检请求直接返回空响应体 } } })
postMessage
-
window属性
-
跨窗口,跨框架frame、iframe,跨域
-
允许不同源脚本采用异步方式进行有限通信
otherWindow.postMessage(message, targetOrigin, [transfer]) // otherWindow: iframe.contentWindow 属性 window.open 返回 window.frames 访问 window.onmessage = e => console.log(e.data) // 接收返回数据
Websocket
-
基于 TCP
-
全双工通信
-
应用层协议
// 客户端 const socket = new WebSocket('ws://localhost:3000') socket.onopen = () => socket.send('message') // 向服务器发送数据 soket.onmessage = e => console.log(e.data) // 接收服务器返回数据 // server.js const express = require('express') const app = express() const ws = require('ws') const wss = new ws.Server({port: 3000}) wss.on('connection', ws => { ws.on('message', data => console.log(data)) })
代理服务器转发
-
代理服务器设置 CORS 请求头字段
- nginx
- add_header
- kangle
- 回应控制,增加表,标记模块,add_header
- nodejs
- response.writeHead
- nginx
-
代理服务器向源服务器继续请求
- nginx
-
七层 HTTP 代理:配置 http
http { server { listen 80; location / { proxy_pass http://127.0.0.1:3000 } } }
-
四层 TCP 代理:配置 stream
steam { upstream proxyServer { server 127.0.0.1:3000; } server { listen 80; proxy_pass proxyServer; } }
-
- kangle
- 七层 HTTP 代理
- 请求控制,增加表
- 目标设置为代理
- 匹配模块设置原域名和端口,标记模块设置目标域名和端口
- 七层 HTTP 代理
- nodejs
- 七层 HTTP 代理
const http = require('http') http.request({ host: '127.0.0.1', port: 3000, url: '/' })
- nginx
document.domain
- 主域名相同,子域名不同
- 设置值为 主域名
iframe
- window.name
- 不超过 2MB
- 同一个iframe
- 加载跨域页,跨域页设置 window.name
- 加载同域页,读取 iframe.contentWindow.name
- location.hash
- 不会被 URL 编码
- 加载跨域页,参数跟在 # 后。window.onhashchange 监听 hash 变化
- 跨域页获取 location.hash,加载同域页,参数跟在 # 后
- 同域页设置 window.parent.parent.location.hash = location.hash,将参数回传