跨域解决方法,jsonp和cors的优劣性

跨域解决方法

虽然在安全层面上同源限制是必要的,但有时同源策略会对我们的合理用途造成影响,为了避免开发的应用受到限制,有多种方式可以绕开同源策略,下面介绍的是经常使用的 JSONP, CORS 方法。

JSONP

原理:

  • JSONP 是一种非官方的跨域数据交互协议
  • JSONP 本质上是利用

    然后,我们就可以借助

    这时服务端在返回数据的时候,就会返回一端 Javascript 代码,在 Javascript代码中调用了回调函数,并且需要返回的数据作为回调函数的参数

    dosomething(['a','b','c']);
    

    最后页面成功加载了刚才指定路径的资源后,将会执行该 Javascript 代码,dosomething函数将执行,这时一次跨域请求完成。

    另外,如果页面引入了 jQuery,那么可以通过它封装的方法很方便的实现JSONP操作了

    // Using YQL and JSONP
    $.ajax({
        url: "http://query.yahooapis.com/v1/public/yql",
     
        // The name of the callback parameter, as specified by the YQL service
        jsonp: "callback",
     
        // Tell jQuery we're expecting JSONP
        dataType: "jsonp",
     
        // Tell YQL what we want and that we want JSON
        data: {
            q: "select title,abstract,url from search.news where query=\"cat\"",
            format: "json"
        },
     
        // Work with the response
        success: function( response ) {
            console.log( response ); // server response
        }
    });
    

    优缺点:

    JSONP 的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行。

    JSONP 的缺点是:它只支持 GET 请求,而不支持 POST 请求等其他类型的 HTTP 请求

    CORS

    介绍

    ​ 跨源资源共享 Cross-Origin Resource Sharing(CORS) 是一个新的 W3C 标准,它新增的一组HTTP首部字段,允许服务端其声明哪些源站有权限访问哪些资源。换言之,它允许浏览器向声明了 CORS 的跨域服务器,发出 XMLHttpReuest 请求,从而克服 Ajax 只能同源使用的限制。

    ​ 另外,规范也要求对于非简单请求,浏览器必须首先使用 OPTION 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求,在服务器确定允许后,才发起实际的HTTP请求。对于简单请求、非简单请求以及预检请求的详细资料可以阅读HTTP访问控制(CORS) 。

    HTTP 协议 Header 简析

    下面对 CORS 中新增的 HTTP 首部字段进行简析:

    • Access-Control-Allow-Origin

      响应首部中可以携带这个头部表示服务器允许哪些域可以访问该资源,其语法如下:

      Access-Control-Allow-Origin:  | *
      

      其中,origin 参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。

    • Access-Control-Allow-Methods

      该首部字段用于预检请求的响应,指明实际请求所允许使用的HTTP方法。其语法如下:

      Access-Control-Allow-Methods: [, ]*
      
    • Access-Control-Allow-Headers

      该首部字段用于预检请求的响应。指明了实际请求中允许携带的首部字段。其语法如下:

      Access-Control-Allow-Headers: [, ]*
      
    • Access-Control-Max-Age

      该首部字段用于预检请求的响应,指定了预检请求能够被缓存多久,其语法如下:

      Access-Control-Max-Age: 
      
    • Access-Control-Allow-Credentials

      该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。其语法如下:

      Access-Control-Allow-Credentials: true
      

      另外,如果要把 Cookie 发送到服务器,除了服务端要带上Access-Control-Allow-Credentials首部字段外,另一方面请求中也要带上withCredentials属性。

      但是需要注意的是:如果需要在 Ajax 中设置和获取 Cookie,那么Access-Control-Allow-Origin首部字段不能设置为* ,必须设置为具体的 origin 源站。详细可阅读文章CORS 跨域 Cookie 的设置与获取

    • Origin

      该首部字段表明预检请求或实际请求的源站。不管是否为跨域请求,Origin字段总是被发送。其语法如下:

      Origin: 
      
    • Access-Control-Request-Method

      该首部字段用于预检请求。其作用是,将实际请求所使用的 HTTP 方法告诉服务器。其语法如下:

      Access-Control-Request-Method: 
      
    • Access-Control-Request-Headers

      该首部字段用于预检请求。其作用是,将实际请求所携带的首部字段告诉服务器。其语法如下:

      Access-Control-Request-Headers: [, ]*
      

    示例

    假设我们在 bbb.cn 域名下,发送一个 Ajax 请求到 aaa.cn 域名,其路径如下:http://aaa.cn/localserver/api/corsTest 。由于同源策略,这样的 Ajax 请求将会被浏览器所拦截,得到下面的信息:

    若想能够发送跨域请求,我们只需要在服务器的响应中配置适当的CORS HTTP 首部字段就可以了,例如可以加入以下的首部字段:

    Access-Control-Allow-Methods:*
    

    此时,Ajax请求就可以顺利的发送和接收了,对应的请求和响应头部如下:

    跨域解决方法,jsonp和cors的优劣性_第1张图片

    跨域解决方法,jsonp和cors的优劣性_第2张图片

    对于在 Java Web 项目中,如何在 Servlet 或这 Spring MVC 中配置 CORS 可以阅读文章Spring MVC 实现 CORS 跨域 。

    与 JSONP 的比较

    • JSONP 只能实现 GET 请求,而 CORS 支持所有类型的 HTTP 请求
    • 使用 CORS ,开发者可以是使用普通的 XMLHttpRequest 发起请求和获取数据,比起 JSONP 有更好的错误处理
    • 虽然绝大多数现代的浏览器都已经支持 CORS,但是 CORS 的兼容性比不上 JSONP,一些比较老的浏览器只支持 JSONP



    作者:ken_ljq
    链接:https://www.jianshu.com/p/f880878c1398
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

你可能感兴趣的:(跨域解决方法,jsonp和cors的优劣性)