# cross_domain **Repository Path**: aeipyuan/cross_domain ## Basic Information - **Project Name**: cross_domain - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-04-29 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 实现跨域方式 ### 1. jsonp方式 原理:script标签不受同源策略的影响,把链接挂在script标签上,通过回调函数传递数据 优点:兼容性好,前后端分离 缺点:仅支持get请求,安全性较差,容易引发xss攻击 ``` javascript /* server.js */ const express = require('express'); const app = express(); app.get('/say', (req, res) => { let { wd, cb } = req.query; console.log('客户端:' + wd);//客户端:Hello res.end(`${cb}('服务端:Hi')`) }) app.listen(3333, () => { console.log("Server start http://localhost:3333"); }) ``` ``` html ``` ### 2. CORS 原理:通过在服务端添加白名单,放宽对请求源的限制,从而实现跨域 **3333端口下的indexhtml发出ajax请求** ``` html ``` **4444端口服务器对数据进行处理** ``` javascript const express = require('express'); const app = express(); /* 设置白名单 */ let writeList = ['http://localhost:3333']; app.use((req, res, next) => { /* 获取请求源 */ let { origin } = req.headers; /* 判断请求源 */ if (writeList.includes(origin)) { /* 允许origin访问 */ res.setHeader('Access-Control-Allow-Origin', origin) /* 允许哪个头 */ res.setHeader('Access-Control-Allow-Headers', 'name') /* 允许哪个方法 */ res.setHeader('Access-Control-Allow-Methods', 'PUT') /* 允许携带cookie */ res.setHeader('Access-Control-Allow-Credentials', true) /* 预检的存活时间 */ res.setHeader('Access-Control-Allow-Max-Age', 6) /* 允许前端获取哪个头 */ res.setHeader('Access-Control-Expose-Headers', 'name') /* OPTIONS请求不做处理 */ if (req.method === 'OPTIONS') { res.end(); } } next(); }) app.put('/getData', (req, res) => { console.log(req.headers); res.setHeader('name', 'B'); res.send('4444已收到'); }) app.listen(4444, () => { console.log("Server start http://localhost:4444"); }) ``` ### 3. postMessage实现跨域 原理:将另一个域的网页放到iframe中,利用postMessage进行传值 **3333端口下的a.html** ```html
AAAAAAA
``` **4444端口下的b.html** ``` html
BBBBBB
``` ### 4. window.name传值 原理:先用iframe的window.name存储跨域页面要传入的数据,然后将iframe的src属性改变为同源src,实现获取name存储的值 ``` javascript 举例: A,B页面在3333端口下,C页面在4444端口下,目标是实现a页面获取c页面数据 第一步,A页面用iframe标签引入C页面 第二步,C页面设置window.name=数据 第三步,将iframe的src由C页面切换为B页面(同源) 第四步,获取iframe页面的window.name属性 ``` ```html ``` ### 5. hash传值 原理:和window.name相似,A使用iframe引入C并给C传hash值,C使用iframe引入B并给B传hash值,B和A同源,所以把hash值赋给A,A监听到hash变化输出hash值 ``` html ``` ### 6. Websocket 原理:Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了 开启服务 ``` javascript /* server.js */ let WebSocket = require('ws'); /* 创建服务 */ let wss = new WebSocket.Server({ port: 3333 }); wss.on('connection', ws => { ws.on('message', e => { console.log(e);//前端数据 ws.send('后台数据'); }) }) ``` 传送数据 ```html ``` ### 7. domain实现跨域 不同的页面可能放在不同的服务器上,这些服务器域名不同,但是拥有相同的上级域名,比如id.qq.com、www.qq.com、user.qzone.qq.com,它们都有公共的上级域名qq.com ,设置页面documen.domain为上级域名即可实现跨域 ``` html
AAAAA
BBBBB
``` ### 8. nginx实现 在conf文件配置以下参数,了解较浅,日后补充 ``` javascript location / { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; if ($request_method = 'OPTIONS') { return 204; } } ``` ### 9. webpack配置实现跨域 ``` javascript //方式1 webpack.config.js devServer: { port: 8081, contentBase: './build', hot: true, proxy: { '/api': { target: 'http://localhost:8888',//目标域 pathRewrite: { '/api': '' }/* 路径重写 */ } } } //方式2 server.js 直接在8888端口访问webpack打包文件 let express = require('express'); let app = express(); /* webpack */ let webpack = require('webpack'); let config = require('../webpack.config.js'); let compiler = webpack(config); //中间件 let middle = require('webpack-dev-middleware'); app.use(middle(compiler)); /* 请求 */ app.get('/user', (req, res) => { res.json({ name: "aeipyuan" }) }) app.listen(8888); ```