23 前后端跨域问题
跨域(非同源策略请求)
-
同源策略请求 ajax / fetch
-
跨域传输
部署到同一个web服务器上:同源策略
-
产生原因:服务器拆分/调用第三方接口(现在为了服务器性能,负载均衡,对服务器进行了拆分,前端需要请求不同服务器(如不同域名))
web服务器:静态资源
data服务器:业务逻辑和数据分析
图片服务器
-
区分:三者都一样就是同源,只要有一个不同就是跨域
协议
域名
端口号
解决跨域方法
-
JSONP
script img link iframe href … 这些标签不受跨域请求限制
执行过程(以script为例):
思路类似react父组件获取子组件的数据交互:父传一个回调函数给子,子携带数据调用该函数,这样父组件就获取了子组件信息
缺点:jsonp只能处理get请求,安全性差
-
CORS跨域资源共享(服务端的一个middle ware 中间件)
客户端(发送ajax / fetch请求)
服务器端设置相关的头信息(需要处理options试探性请求)
补充链接:
//核心代码
res.header('Access-Control-Allow-Origin', '*'); //这个表示任意域名都可以访问,这样写不能携带cookie了。
//res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //这样写,只有www.baidu.com 可以访问。但是可以携带cookie
res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');//设置允许跨域的请求头
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//设置方法
if (req.method == 'OPTIONS') {
res.send(200); // 意思是,在正常的请求之前,会发送一个验证,是否可以请求。(针对put,delete这种CORS非简单请求就会发送预检请求,响应成功后再执行正常的请求)
}
else {
next();
}
/*
Access-Control-Allow-Origin
这个请求头一般会被服务器端返回,它的值代表了哪些域名你有权可以访问。 它的值可以为:
*允许访问任何域
一个安全验证过的域名(eg. example.com)
如果你请求客户端传一些用作验证的请求头,比如cookies, 那么你就不能将Access-Control-Allow-Origin的值设定为*—必须是安全验证过的域名才可以!
Access-Control-Allow-Credentials(请求需要携带cookie也需要写)
如果一个服务器支持通过cookies来验证,那么必须要在响应里带上这个请求头。True是其唯一有有效的值。
Access-Control-Allow-Headers(一些特殊请求头,自定义请求头就需要写上)
一个逗号分隔的list,存放代表服务器愿意支持的请求头。(eg. 比如x-authentication-token, 你需要将其包含在ACA header里, 返回给前面提到的options请求, 否则你的请求会被blocked)
Access-Control-Expose-Headers(非必须)
跟上面相似,这个请求头包含一系列用户可用的headers,这些headers会出现在真实响应里,而且客户端是可以使用的。其他的所有header会被blocked。
Access-Control-Allow-Methods
这个比较简单,存放所有服务端支持的HTTP请求类型(比如get,post)。
*/
-
http proxy (配合webpack webpack-dev-server)
为什么可以不受跨域问题限制?
proxy相当于node给你模拟了一个nginx服务请求,服务器请求服务器不存在跨域。proxy请求回来数据,解决跨域
-
nginx反向代理
server {
listen 80; #监听端口
server_name www.a.com; #nginx服务器也就是前端所在地址
location /api {
proxy_pass www.b.com; #识别api转发到服务器的地址
add_header Access-control-Allow-Origin *; #类似cors的请求头设置
}
}