前后端分离的时代,前端需要通过 ajax 向服务端请求数据来渲染页面,由于浏览器的同源策略限制,就会导致请求跨域的问题。接下来提供几种解决跨域的方案。
浏览器的同源策略
同源策略主要是浏览器为了安全请求服务端资源做了限制,不允许前端访问不同源的资源,禁止跨域访问。
如何解决跨域
既然浏览器默认禁止跨域访问,只需要在请求资源时候服务器告诉浏览器允许前端访问该资源,浏览器就会放开限制,下面介绍解决跨域常见的几种方式
JSONP 实现
JSONP 本质上是利用了 script 标签不受跨域限制的特性,客户端声明一个全局函数,可以让服务器返回一个执行该函数的脚本,即可获取到服务端返回的数据。
- 客户端声明一个全局函数
<script>
// 声明一个函数
function getUserList(res) {
alert(JSON.stringify(res));
}
</script>
- 客户端请求后端接口,通过参数把上面定义的函数名(getUserList)传递给后端
var script = document.createElement("script");
script.type = "text/Javascript";
// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = "https://www.aaa.com/getUserList?callback=getUserList";
document.head.appendChild(script);
- 服务端接收到客户端传递过来的参数(getUserList),序列化响应数据,拼接成可执行的字符串函数,返回给客户端,客户端接受到该函数就会立刻执行。这时
getUserList
函数就可以获取到服务端的数据了。
server.on("request", function (req, res) {
const { callback } = req.query;
// jsonp返回设置
res.writeHead(200, { "Content-Type": "text/Javascript" });
res.write(callback + "(" + JSON.stringify(params) + ")");
res.end();
});
到这里一个 jsonp 的请求流程就完成了
注意:JSONP 有一个严重的缺点是只能 get 请求,不能执行 post 请求
nodejs 服务代理
平时在开发前端项目,可以通过 webpack.config.js
文件来配置 proxy
属性来解决请求跨域的问题。底层的原理是利用服务端没有跨域一说,跨域是浏览器才会
proxyTable: {
'/apis':{
target: 'http://api.abc.com/', // 后台api
changeOrigin: true, //是否跨域
// secure: true,
pathRewrite: {
'^/apis': '' //需要rewrite的,
}
}
}
nginx 代理转发
server {
listen 80;
server_name www.abc.com;
location /api/ {
proxy_pass https://api.abc.com;
}
}
服务器配置响应头 cors
Access-Control-Allow-Origin
后端开发可以通过配置接口服务的响应头来允许跨域请求访问资源,*
代表允许所有来源,也可以手动指定白名单
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: https://1024nav.com
Access-Control-Allow-Headers
设置服务器允许访问携带的请求头,一般在预检请求用到,告诉浏览器允许接受哪些自定义头
Access-Control-Allow-Headers: LANG
Access-Control-Allow-Methods
设置服务器允许的请求方法,一般在预检请求会告诉客户端允许使用的方法,例如 GET,POST,PUT 等等
Access-Control-Allow-Methods: POST, GET, OPTIONS