什么是跨域

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源。

如何跨域

在项目开发中,时常遇见浏览器接口请求需要跨域访问的情况,此时,我们该如何访问呢?

下面是几种常用的跨域解决方案:

通过JSONP跨域

接口通过jsonp格式请求,请求中需带上callback字段,传递回调方法名,服务端返回结果需要以回调参数的形式返回。

在页面上我们可以引入不同域上的js脚本文件,但是无法通过ajax访问接口,jsonp的原理是通过一个js脚本回调达到跨域请求的效果。

服务端设置响应头

服务端设置Access-Control-Allow-Origin响应头为 *,表示允许所有请求跨域访问,也可以设置为具体域名或IP,达到允许制定地址访问。

1
2

response.setHeader("Access-Control-Allow-Origin", "*");

此时需要加上前端header头 ‘Content-Type’: ‘application/x-www-form-urlencoded’

如果跨域请求需要携带cookie信息:

此时服务端需要设置响应头

1
2
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

而前端代码ajax请求需要加上withCredentials = true属性,允许携带cookie,

代理服务器

如果是前后端分离的项目,前端开发阶段可以通过webpack或者gulp构建本地服务器并设置转发。

如webpack配置

1
2
3
4
5
6
7
8
9
devServer: {
historyApiFallback: true,
noInfo: true,
proxy: {
'/menu': {
target: 'https://other-server.example.com',
secure: false
}
}

也可以手写一个node express代理转发,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const express = require('express');
const path = require('path');
const timeout = require('connect-timeout');
const proxy = require('http-proxy-middleware');
const app = express();

// 这里从环境变量读取配置,方便命令行启动
// HOST 指目标地址
// PORT 服务端口
// const { HOST = 'http://api.zhuishushenqi.com', PORT = '3300' } = process.env;

// 超时时间
const TIME_OUT = 30 * 1e3;

// 设置端口
app.set('port', 1337);

// 设置超时 返回超时响应
app.use(timeout(TIME_OUT));
app.use((req, res, next) => {
if (!req.timedout) next();
});

// 静态页面
// 这里一般设置你的静态资源路径
app.use('/', express.static(__dirname));

// 反向代理(这里把需要进行反代的路径配置到这里即可)
// eg:将/api/test 代理到 ${HOST}/api/test
app.use('/api1', proxy({
target: 'http://api.zhuishushenqi.com', pathRewrite: {
'^/api1': '/'
},
changeOrigin: true
}));

app.use('/api2', proxy({
target: 'http://chapterup.zhuishushenqi.com', pathRewrite: {
'^/api2': '/'
},
changeOrigin: true
}))

// 监听端口
app.listen(app.get('port'), () => {
console.log(`server running @${app.get('port')}`);
});

把这个js文件放在根目录,用node启动,在本地进行ajax请求时,加上特定的url标识,就能正常转发了。

如果使用nginx作为服务器,可以添加配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

upstream my_server {
server 10.0.0.2:8080;
keepalive 2000;
}
server {
listen 80;
server_name 10.0.0.1;
client_max_body_size 1024M;

location /my/ {
proxy_pass http://my_server;
proxy_set_header Host $host:$server_port;
}
}

在这里我只针对了常用的几种跨域方式进行了介绍,还有不同类型的其他跨域方式,如同源跨域,设置domain,或者postMessage,或者window.name,这里就不一一介绍了。