资讯专栏INFORMATION COLUMN

前端跨域资源请求: JSONP/CORS/反向代理

番茄西红柿 / 2060人阅读

摘要:此时完成的跨域代理配置仅仅是在开发环境下生效,到了生产环境下如果是放到服务器上则还需要借助的反向代理来进行跨域的代理。

跨域 指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对 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-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在 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 的反向代理来进行跨域的代理。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/989.html

相关文章

  • 004. 前端跨域资源请求JSONP/CORS/反向代理

    摘要:同源策略浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。不受同源策略限制的跨域资源的引入是允许的页面中的链接,重定向以及表单提交是不会受到同源策略限制的。1.什么是跨域资源请求? https://www.cnblogs.com/niuli1987/p/10252214.html 同源: 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相...

    番茄西红柿 评论0 收藏0
  • jsonp跨域获取数据实现百度搜索

    摘要:同源策略做了很严格的限制,但是在实际的场景中,又确实有很多地方需要突破同源策略的限制,也就是我们常说的跨域。使用跨域由于同源策略,一般来说位于的网页无法与不是的服务器沟通,而的元素是一个例外。 本菜鸡最近在写某个页面请求数据时,报了如下的错误。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...

    Tikitoo 评论0 收藏0
  • jsonp跨域获取数据实现百度搜索

    摘要:同源策略做了很严格的限制,但是在实际的场景中,又确实有很多地方需要突破同源策略的限制,也就是我们常说的跨域。使用跨域由于同源策略,一般来说位于的网页无法与不是的服务器沟通,而的元素是一个例外。 本菜鸡最近在写某个页面请求数据时,报了如下的错误。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...

    gggggggbong 评论0 收藏0
  • jsonp跨域获取数据实现百度搜索

    摘要:同源策略做了很严格的限制,但是在实际的场景中,又确实有很多地方需要突破同源策略的限制,也就是我们常说的跨域。使用跨域由于同源策略,一般来说位于的网页无法与不是的服务器沟通,而的元素是一个例外。 本菜鸡最近在写某个页面请求数据时,报了如下的错误。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...

    lemanli 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<