前端跨域-jsonp、CROS、配置反向代理

跨域 指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对 JavaScript 施加的安全限制。
同源就是指 域名,协议,端口 均相同。两个网域若 域名、协议、端口 任一不同则二者的通信就出现了跨域问题,前端的跨域问题普通存在于两个阶段,一个是开发环境调试阶段,另一个发布上线后的生产环境运行阶段,一般生产环境下的跨域问题会由运维或实施人员来解决,但是开发环境下的跨域问题需要前端或后端进行处理

常见的跨域解决方案

1.jsonp 跨域

jsonp 是数据格式 JSON 的一种“使用模式”,可以让网页从别的网站索要数据,jsonp 的原理就是利用 <script> 标签没有跨域限制,通过 <script> 标签 src 属性,发送带有 callback 参数的 GET 请求服务端将接口返回数据拼凑到 callback 函数中返回给浏览器,浏览器解析执行,从而前端拿到 callback 函数返回的数据
:用 JSONP 抓到的数据并不是 JSON而是任意的 JavaScript ,用 JavaScript 解释器运行而不是用 JSON 解析器解析。所以通过 Chrome 查看所有 JSONP 发送的 Get 请求都是 js 类型,而非 XHR 。

下面演示下使用原生 JS 和 Ajax 实现 jsonp 跨域的写法:

原生 JS 写法

     <script>
        // 回调执行函数
        function handleCallback(res) {
            console.log(res);  // {user: 'admin', callback: 'handleCallback'}
        }
     </script>
     <script type="text/javascript" src="http://127.0.0.1:8080/login?user=admin&callback=handleCallback"></script>
    

Ajax 写法:

        $.ajax({
            // 需要跨域获取数据的网站 URL
            url: 'http://127.0.0.1:8080/login?user=admin',
            // 请求类型,JSONP 只支持 GET 请求,可以不写,默认也是 GET 类型
            method: 'GET',
            // 使用 $.ajax() 发起 JSONP 请求,必须指定 dataType: 'jsonp'
            dataType: 'JSONP',
            // jsonpCallback 用于设置回调函数的函数名称
            jsonpCallback: 'handleCallback',
            // success 用于接收请求成功后的返回值
            success: function (res) {
                console.log(res);
            }
        })

应用场景:有些第三方数据接口可能会使用 jsonp 解决跨域,在实际工作中并不怎么用这种方式解决跨域问题。主要是因为 jsonp 只支持 GET 请求,请求方式单一不能满足开发需求,这也是 jsonp 的致命缺点。

2.中间服务器代理

跨域问题只存在于浏览器中,服务器端没有跨域的概念。中间服务器代理的思路就是我们前端可以不跨域的去访问一个中间服务器(这个中间服务器和我们前端网域的 域名、协议、端口都相同,则不跨域),再让中间服务器去替我们访问这个我们本来需要跨域访问的网站,中间服务器拿到我们需要的资源然后再返还给我们即可。

这主要是一种解决跨域的思路,下面我们会介绍到在 Vue 项目中配置 反向代理 来解决跨域问题时其实就是使用的这种中间服务器代理的思路

3.CORS 跨域资源共享

 CORS 是一个 W3C 标准,全称是"跨域资源共享"。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

浏览器将 CORS 请求分为简单请求和非简单请求。对于简单请求,浏览器直接发出 CORS 请求,具体来说就是在头信息中,增加一个 Origin 字段。服务器会根据这个字段决定是否同意此次请求。而非简单请求就是对服务器有特殊要求的请求,比如 PUT 请求、DELETE 请求等,非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为“预检请求”(preflight),预检请求的请求类型是 OPTIONS 表示询问,服务器会先对预检请求进行回应,如果允许了此次的跨域才会发起正式的非简单请求,所以非简单请求实际上会有两次请求记录(一次预检请求一次正式请求)。

简单来说实现 CORS 跨域资源共享其实就是在发起请求前或在服务器端进行请求头、请求类型等配置,符合配置项条件的请求就可以正常与该服务器进行通信。

简单请求中重要配置字段如下

Access-Control-Allow-Origin 是必须的配置项,它的值要么是请求时 Origin 字段的值(包含:协议、域名、端口),要么是一个 * ,表示接受任意域名的请求。

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials 该字段可选。它的值是一个布尔值,表示是否允许发送 Cookie 。默认情况下,Cookie不包括在CORS请求之中。设为 true ,即表示服务器明确许可,Cookie 可以包含在请求中,一起发给服务器。这个值也只能设为 true ,如果服务器不要浏览器发送 Cookie ,删除该字段即可。
Access-Control-Allow-Credentials: true

Access-Control-Expose-Headers 该字段可选。CORS请求时,XMLHttpRequest 对象的getResponseHeade() 方法只能拿到6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。如果想拿到其他字段,就必须在 Access-Control-Expose-Headers 里面指定。

Access-Control-Expose-Headers: FooBar

非简单请求的配置

非简单请求除了需要配置 Origin 字段外,一般还需要配置如下字段:

 Access-Control-Allow-Methods字段是必须的,用来列出浏览器的 CORS 请求会用到哪些HTTP方法。如 PUT 、DELETE 等

Access-Control-Allow-Methods: POST, GET, OPTIONS

Access-Control-Request-Headers 该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

Access-Control-Request-Headers: X-Custom-Header

CORS 跨域资源共享可以在前端或后端进行配置,是目前常用的解决浏览器跨域的方案,较之 jsonp 其更加强大,几乎支持所有的请求类型。

4.配置反向代理实现跨域的方法

配置反向代理 是前端自行在项目中进行配置来解决跨域的一种方式,主要就是在项目中设置代理,开启代理就会在本地创建一个虚拟服务器,我们会通过它来发送请求,它也会把请求返回的数据返还给我们。主要就是使用中间服务器代理的思路。

Vue 项目中配置反向代理:(分为 CLI 2.X 和 CLI 3.X 搭建的项目)

CLI 2.X 搭建的项目配置路径:打开项目的 config/index.js 文件,找到 dev 中的 proxyTable: {}, 字段,(如果没有就添加一个),将该字段进行如下配置:

        // 设置代理
        proxyTable: {
            // 需要代理的接口,当地址中有 /api 时就会触发代理机制
            '/api': {
                target: 'http://39.97.33.178', // 目标服务器域名
                    ws: true,  // 是否启用 websockets,就开启即可
                        changeOrigin: true, // 是否跨域,需要设置此值为 true 才可以让本地服务器代理我们发出请求
                            pathRewrite: {	// 路径重写
                    '^/api': ''             //重定向,即服务器端是否需要将匹配到的值替换成其他值来进行数据请求,假设我们想把 localhost:8888/api/login 变成 http://39.97.33.178/login 就需要这么做
                }
            }
        },

CLI 3.X 搭建的项目默认的配置文件是隐藏的,需要手动在根目录创建一个 vue.config.js 文件,在该文件中 进行如下配置:

        // 设置代理
        modele.exports = {
            devServer: {
                // 设置代理
                proxy: {
                    // 需要代理的接口,当地址中有 /api 时就会触发代理机制
                    '/api': {
                        target: 'http://39.97.33.178', // 目标服务器域名
                        ws: true,  // 是否启用 websockets,就开启即可
                        changeOrigin: true,  // 是否跨域,需要设置此值为 true 才可以让本地服务器代理我们发出请求
                        pathRewrite: {
                            '^/api': ''  // 重定向,即服务器端是否需要将匹配到的值替换成其他值来进行数据请求,假设我们想把 localhost:8888/api/login 变成 http://39.97.33.178/login 就需要这么做
                        }
                    }
                },
            }
        }

注意:vue.config.js 的改动如果需要生效,需要进行重启服务
此时完成的跨域代理配置仅仅是在开发环境下生效,到了生产环境下如果是放到 Nginx 服务器上则还需要借助 Nginx 的反向代理来进行跨域的代理

本文主要简单介绍了四种前端实现跨域的方案,更多方法和详情推荐文章:9种常见的前端跨域解决方案

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值