解决前端跨域请求的几种方式

利用 JSONP 实现跨域调用

说道跨域调用,可能大家首先想到的或者听说过的就是 JSONP 了。

1.1 什么是JSONP

JSONP 是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问问题。其原理是根据 XmlHttpRequest 对象受到同源策略的影响,而 <script> 标签元素却不受同源策略影响,可以加载跨域服务器上的脚本,网页可以从其他来源动态产生 JSON 资料。用 JSONP 获取的不是 JSON 数据,而是可以直接运行的 JavaScript 语句。

1.2 使用 jQuery 集成的 $.ajax 实现 JSONP 跨域调用

下面的例子,我们将 服务器 3000 上的请求页面的 JavaScript 代码为:

// 回调函数
function jsonpCallback(data) {
    console.log("jsonpCallback: " + data.name)
}
$("#submit").click(function() {
    var data = {
        name: $("#name").val(),
        id: $("#id").val()
    };
    $.ajax({
        url: ‘http://localhost:3001/ajax/deal‘,
        data: data,
        dataType: ‘jsonp‘,
        cache: false,
        timeout: 5000,
        // jsonp 字段含义为服务器通过什么字段获取回调函数的名称
        jsonp: ‘callback‘,
        // 声明本地回调函数的名称,jquery 默认随机生成一个函数名称
        jsonpCallback: ‘jsonpCallback‘,
        success: function(data) {
            console.log("ajax success callback: " + data.name)
        },
        error: function(jqXHR, textStatus, errorThrown) {
            console.log(textStatus + ‘ ‘ + errorThrown);
        }
    });
});

 服务器 3001 上对应的处理函数为:

1 app.get(‘/ajax/deal‘, function(req, res) {
2     console.log("server accept: ", req.query.name, req.query.id)
3     var data = "{" + "name:‘" + req.query.name + " - server 3001 process‘," + "id:‘" + req.query.id + " - server 3001 process‘" + "}"
4     var callback = req.query.callback  //获得请求端回调函数
5     var jsonp = callback + ‘(‘ + data + ‘)‘
6     console.log(jsonp)
7     res.send(jsonp)
8     res.end()
9 })

这里一定要注意 data 中字符串拼接,不能直接将 JSON 格式的 data 直接传给回调函数,否则会发生编译错误: parsererror Error: jsonpCallback was not called

1.3 使用 <script> 标签原生实现 JSONP

经过上面的事件,你是不是觉得 JSONP 的实现和 Ajax 大同小异?

其实,由于实现的原理不同,由 JSONP 实现的跨域调用不是通过 XmlHttpRequset 对象,而是通过 script 标签,所以在实现原理上,JSONP 和 Ajax 已经一点关系都没有了。看上去形式相似只是由于 jQuery 对 JSONP 做了封装和转换。

比如在上面的例子中,我们假设要传输的数据 data 格式如下:

{
    name: "chiaki",
    id": "3001"
}

那么数据是如何传输的呢?HTTP 请求头的第一行如下:

GET /ajax/deal?callback=jsonpCallback&name=chiaki&id=3001&_=1473164876032 HTTP/1.1

可见,即使形式上是用 POST 传输一个 JSON 格式的数据,其实发送请求时还是转换成 GET 请求。

其实如果理解 JSONP 的原理的话就不难理解为什么只能使用 GET 请求方法了。由于是通过 script 标签进行请求,所以上述传输过程根本上是以下的形式:

<script src = ‘http://localhost:3001/ajax/deal?callback=jsonpCallback&name=chiaki&id=3001&_=1473164876032‘></script>

这样从服务器返回的代码就可以直接在这个 script 标签中运行了。下面我们自己实现一个 JSONP:

  • 服务器 3000请求页面的 JavaScript 代码中,只有回调函数 jsonpCallback:
  • function jsonpCallback(data) {
        console.log("jsonpCallback: "+data.name)
    }

    服务器 3000请求页面还包含一个 script 标签:

  • <script src = ‘http://localhost:3001/jsonServerResponse?jsonp=jsonpCallback‘></script>

    服务器 3001上对应的处理函数:

    1 app.get(‘/jsonServerResponse‘, function(req, res) {
    2     var cb = req.query.jsonp //这里得到请求页面的回调函数
    3     console.log(cb)      //思考一下为什么这里要这样写
    4     var data = ‘var data = {‘ + ‘name: $("#name").val() + " - server 3001 jsonp process",‘ + ‘id: $("#id").val() + " - server 3001 jsonp process"‘ + ‘};‘
    5     var debug = ‘console.log(data);‘ //打印var data="";
    6     var callback = ‘$("#submit").click(function() {‘ + data + cb + ‘(data);‘ + debug + ‘});‘
    7     res.send(callback) //返回的是一个点击按钮的事件
    8     res.end()
    9 })

    与上面一样,我们在所获取的参数后面加上 “ - server 3001 jsonp process” 代表服务器对数据的操作。从代码中我么可以看到,处理函数除了根据参数做相应的处理,更多的也是进行字符串的拼接。

  • 2.4 JSONP 总结

    至此,我们了解了 JSONP 的原理以及实现方式,它帮我们实现前端跨域请求,但是在实践的过程中,我们还是可以发现它的不足:

    1. 只能使用 GET 方法发起请求,这是由于 script 标签自身的限制决定的。
    2. 不能很好的发现错误,并进行处理。与 Ajax 对比,由于不是通过 XmlHttpRequest 进行传输,所以不能注册 success、 error 等事件监听函数
    3. 使用 CORS 实现跨域调用

      3.1 什么是 CORS?

      Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。

    4. 3.2 CORS 的实现

      还是以 服务器 3000 上的请求页面向 服务器 3001 发送请求为例。

      • 服务器 3000 上的请求页面 JavaScript 不变,服务器 3001上对应的处理函数:
      •  1 app.post(‘/cors‘, function(req, res) {
         2     res.header("Access-Control-Allow-Origin", "*"); //设置请求来源不受限制
         3     res.header("Access-Control-Allow-Headers", "X-Requested-With");
         4     res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); //请求方式
         5     res.header("X-Powered-By", ‘ 3.2.1‘)
         6     res.header("Content-Type", "application/json;charset=utf-8");
         7     var data = {
         8         name: req.body.name + ‘ - server 3001 cors process‘,
         9         id: req.body.id + ‘ - server 3001 cors process‘
        10     }
        11     console.log(data)
        12     res.send(data)
        13     res.end()
        14 })

        3.3 CORS 中属性的分析

        1. Access-Control-Allow-Origin

          The origin parameter specifies a URI that may access the resource. The browser must enforce this. For requests without credentials, the server may specify “*” as a wildcard, thereby allowing any origin to access the resource.

        2. Access-Control-Allow-Methods

          Specifies the method or methods allowed when accessing the resource. This is used in response to a preflight request. The conditions under which a request is preflighted are discussed above.

        3. Access-Control-Allow-Headers

          Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request.

          3.4 CORS 与 JSONP 的对比

          1. CORS 除了 GET 方法外,也支持其它的 HTTP 请求方法如 POST、 PUT 等。
          2. CORS 可以使用 XmlHttpRequest 进行传输,所以它的错误处理方式比 JSONP 好。
          3. JSONP 可以在不支持 CORS 的老旧浏览器上运作。
时间: 2024-10-16 13:03:26

解决前端跨域请求的几种方式的相关文章

跨域请求的3种方式

视频教程 跨域请求的方式:3种 1.后台代理 2.jsonp 3.HTML5中的XHR2 需要前端会的方法是后两种. 2.jsonp使用方法:只支持get方式 $.ajax({dataType:"jsonp",jsonp:"callback",success:...,error:...});//前台,修改数据类型,定义jsonp属性和参数名,等待后台调用 var request=$_GET("callback");//后台,接收前台定义好的参数名

前端跨域请求原理及实践

前端跨域请求原理及实践 2017-03-03 前端大全 (点击上方公众号,可快速关注) 作者:高鹏 tingandpeng.com/2016/09/05/前端跨域请求原理及实践/ 如有好文章投稿,请点击 → 这里了解详情 一. 跨域请求的含义 浏览器的同源策略,出于防范跨站脚本的攻击,禁止客户端脚本(如 JavaScript)对不同域的服务进行跨站调用. 一般的,只要网站的 协议名protocol. 主机host. 端口号port 这三个中的任意一个不同,网站间的数据请求与传输便构成了跨域调用.

用iframe设置代理解决ajax跨域请求问题

面对ajax跨域请求的问题,想用代理的方式来解决这个跨域问题.在服务器端创建一个静态的代理页面,在客户端用iframe调用这个代理 今天在项目中需要做远程数据加载并渲染页面,直到开发阶段才意识到ajax跨域请求的问题.于是想用代理的方式来解决这个跨域问题. 什么是跨域?简单的来说,出于安全方面的考虑,页面中的JavaScript无法访问其他服务器上的数据,即"同源策略".而跨域就是通过某些手段来绕过同源策略限制,实现不同服务器之间通信的效果. 方案:在服务器端创建一个静态的代理页面,在

.net mvc webapi 解决前端跨域问题

跨域问题的原因不解释了,直接设置两步就可以解决前端跨域问题 1.Gloabel.asax文件中 //解决跨域问题 protected void Application_BeginRequest(object sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.Resp

webapi 解决ajax跨域请求问题

webapi在配置文件中加入这几句就可以解决浏览器跨域请求调用的问题?为什么呢? <system.webServer> <validation validateIntegratedModeConfiguration="false" /> <modules runAllManagedModulesForAllRequests="true" /> <httpProtocol> <customHeaders> &

Nodejs解决所有跨域请求

Nodejs解决所有跨域请求 app.use(function(req, res, next) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST'); res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorizati

JAVA解决前端跨域问题。

什么是跨域? 通俗来说,跨域按照我自己的想法来理解,是不同的域名之间的访问,就是跨域.不同浏览器,在对js文件进行解析是不同的,浏览器会默认阻止,所以 现在我来说下用java代码解决前端跨域问题. 用java代码解决前端跨域问题? 找到WEB-INF下面的web.xml文件,输入下面代码,在web.xml文件下面: 1 <!-- 解决跨域访问的问题 --> 2 <filter> 3 <filter-name>cors</filter-name> 4 <

如何解决ajax跨域请求?

1.什么是跨域? a.域名不同 b.域名相同,端口不同 注:只有域名相同,端口相同时,才可以访问数据 可以使用jsonp解决ajax跨域请求的问题. 2.什么是jsonp? Jsonp其实就是一个跨域解决方案.Js跨域请求是不可以的,但是js跨域请求js脚本是可以的.可以把数据封装成一个js语句,做一个方法的调用.跨域请求js脚本可以得到此脚本.得到js脚本之后会立即执行.可以把数据作为参数传递到方法中.就可以获得数据.从而解决跨域请求的问题. 原文地址:https://www.cnblogs.

System.Web.Http.Cors配置跨域访问的两种方式

System.Web.Http.Cors配置跨域访问的两种方式 使用System.Web.Http.Cors配置跨域访问,众多大神已经发布了很多文章,我就不在详细描述了,作为小白我只说一下自己的使用心得.在webapi中使用System.Web.Http.Cors配置跨域信息可以有两种方式.  一种是在App_Start.WebApiConfig.cs的Register中配置如下代码,这种方式将在所有的webapi Controller里面起作用. using System; using Sys