# 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);
```