前端跨域请求方式整理

在日常开发中,前后端数据联调过程中,跨域是我们绕不过去的一个问题,面试的时候,也经常会问到,但是,解决跨域问题大部分都是在后端/服务端去解决的,虽然感觉面试的时候问前端跨域的解决方案有点耍流氓,这里,还是整理下常见的跨域解决方案

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

阮一峰同源政策介绍

JSONP

在前后端分离项目之前,我们用的最多的是 JSONP

原理:

在开发过程中,我们可以发现,script 标签的src img标签的src link标签的src都不会受同源策略的影响,jsonp就是利用script 的scr不受同源策略影响的前提下产生的

在按钮点击(或者其他触发ajax调用)时,手动创建一个script src指向后端接口地址,同时,在地址后加上 callback函数方法名,后端生成对应的js函数调用同时把参数传递到这个callback函数里,我们只要在页面上定义好这个callback方法的处理逻辑即可 例如

$(".btn").on("click",function(){
    var ele = document.createElement('script');
    ele.src = 'http://api.xxx.com/getList?page=1&size=10&callback=getList';
    $("body").append(ele);
})

//callback函数
function getList(arr){
    //处理逻辑

}

从处理方法我们可以看出,jsonp最明显的缺点就是 只支持get请求

CORS 方式 (推荐使用)

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

例如:在php中设置CORS

header("Content-type: application/json");

//跨域
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: 跨域URL");

//CORS
header("Access-Control-Request-Methods:GET, POST, PUT, DELETE, OPTIONS");
header('Access-Control-Allow-Headers:x-requested-with,content-type,test-token,test-sessid');

前端就正常使用ajax发送请求即可

nginx 反向代理 (推荐使用)

在前后端分离的项目中,例如vue-cli创建的项目,开发过程中,我们会配置代理去解决开发环境的跨域问题

vue-cli项目 vue.config.js中配置开发环境代理

module.exports = {
    //公共文件路径
    publicPath: '/',
    //静态资源(js、css、img、fonts)目录
    assetsDir: 'static',
    //代码检测
    lintOnSave: false,
    //sourceMap
    productionSourceMap: false,
    //代理
    devServer:{
        proxy:{
            '/api':{
                target: "https://api.xxx.com",
                pathRewrite: {
                    '^/api': ''
                }
            }

        }
    },
    //css处理
    css: {
        extract: process.env.NODE_ENV === "development" ? false : true
    }
}

如上,我们配置了以 api 开头的请求都会使用代理转发到 https://api.xxx.com 这个接口域名下 代码里我们可以直接以api开头去发送请求

//以api开头的请求会代理到 https://api.xxx.com 这个域名下,实际请求路径为 https://api.xxx.com/getUser
axios.get('/api/getUser').then((res)=>{

})

在项目开发完成后,我们在生产环境部署的时候,可以使用 nginx 设置反向代理 nginx简单配置 在 server下增加如下配置

#接口代理
    location ~ /api/ {
      rewrite ^.+api/?(.*)$ /$1 break;
      proxy_pass https://api.xxx.com;
    }