美文网首页
跨域请求

跨域请求

作者: ZombieBrandg | 来源:发表于2018-06-04 23:05 被阅读0次

    什么是同源策略

    浏览器出于安全的方面考虑,只允许同协议,同域名,同端口下的接口交互,不同源的客户端脚本在没有授权的情况下,不能读写未授权方的资源.

    同源的条件

    • 同协议:比如都是http,或者都是https
    • 同域名:比如baidu.com/a ,baidu.com/b
    • 同端口:比如80端口

    什么是跨域? 有哪些方式

    • JSOP
    • CORS 跨域资源共享(Cross-Origin Resource Sharing)
    • 降域
    • postMessage()

    CORS的原理

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
    它允许浏览器向跨源服务器,发出[XMLHttpRequest]请求,从而克服了AJAX只能[同源]使用的限制。
    CORS重点是需要后端支持才行.

    简单模式:GET POST HEAD

    HTTP的头信息不超出以下几种字段
     Accept
     Accept-Language
     Content-Language
     Last-Event-ID
     Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 
    
    后端添加响应头
    response.setHeader('Access-Control-Allow-Origin','http://xxxx.com')    // 允许xxxx.com跨域请求
    
    

    简单请求:对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
    Origin:http://xxx.com:8888来自源(协议,域名,端口)服务器根据这个值,决定是否同意这次请求。
    如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

    复杂模式: 除了GET POST HEAD

    后端添加响应头
    response.setHeader('Access-Control-Allow-Origin','http://xxxx.com')    // 允许xxxx.com跨域请求
    response.setHeader('Access-Control-Allow-Methods','GET,POST,HEAD,PUT,PATCH,OPTIONS,DELETE'
    
    

    运用方式

    1. 更改本地hosts,映射本地访问 (Mac用sudo方式更改,windows用管理员运行记事本打开hosts更改)

    127.0.0.1 cheche.com

    127.0.0.1 duowan.com

    1. 使用nodejs执行index.js,监听80端口 (Mac用sudo方式更改80端口,windows用管理员运行gitbush更改80端口),并且添加响应头response.setHeader('Access-Control-Allow-Origin','http://duowan.com'),response.setHeader('Access-Control-Allow-Method','get,post,head')让duowan.com获得跨域请求权限
    2. 访问http://cheche.com/cheche,发送AJAX请求http://cheche.com/cheche_prototype.JSON
    3. 访问http://duowan.com/duowan,发送AJAX请求http://cheche.com/cheche_prototype.JSON,这样实现http://duowan.com对http://cheche.com跨域请求

    具体详情参考阮一峰非简单请求

    JSONP

    原理:就是利用<script>标签没有跨域限制来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,形如:
    <script src="http://www.example.net/api?param1=1&param2=2"></script>
    并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。
    第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:
    callback({"name":"cheche","gender":"Male"})
    这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。

    实例

    运行方式

    1. 使用node.js执行index.js监听80端口
    2. 更改本地hosts文件,映射本地访问为
    127.0.0.1 cheche.com
    127.0.0.1 duowan.com
    
    1. 访问http://cheche.com, script会请求http://duowan.com/duowan.js

    具体实现代码

    1. 声明封装一个jsonp的函数,并且传入两个参数url和一个随机的Messagexxx,因为防止多次跨域请求得到的资源不会被覆盖.让每一次请求的资源都能够独立的显示.
     function jsonp(url,fn){
      var Message = 'Message'+parseInt(Math.random()*1000,10)  //生成随机Message
      window[Message] = fn                                     //让这个随机Message是window中的key,这里不使用window.Message主要是因为这个Message是随机每一都不一样.
      var script = document.createElement('script')            //创建一个script标签
      script.src = url+'?callback='+ Message                   //callback是约定俗成的,可以改变为任意参数
      document.head.appendChild(script)                        //利用script的特性,只有在html文档中才会触发请求
     }
    
    1. 在duowan.js中放入要被跨域请求的数据
      {{callback}}({"name":"cheche","gender":"male"}) //{{callback}}是一个占位等待被回调的参数

    2. 在后端中需要添加如下代码

      if(path === "/duowan.js"){
        var string = fs.readFileSync('./duowan.js','utf-8')
        var callback = query.callback                         //利用?查询字符串调取callback的值,这个值就是Message看上边步骤1
        response.setHeader('Content-Type','charset=utf-8')    
        response.end(string.replace('{{callback}}',callback)) //替换string字符串中的{{callback}}为callback,它的值又是Message,Message在window中它的值是function(data){}
      }
    
    1. 在前端执行jsonp函数
      jsonp('http://duowan.com',function(data){
        console.log(第一次数据)
        console.log(data)
      })
      jsonp('http://duowan.com',function(data){
        console.log(第二次数据)
        console.log(data)
      })
    
    1. 得到响应的数据为Message加随机数的执行函数:Message0323({"name":"cheche","gender":"male"})
      第一次的数据
      {"name":"cheche","gender":"male"}
      第二次的数据
      {"name":"cheche","gender":"male"}
      
    

    jQuery也有同样的函数实现JSONP

      $.ajax({
        url:"http://duowan.com/duowan.js"
        dataType:'jsonp'
        success:function(data){
          console.log('第一次执行')
          console.log(data)
        }
        
      })
    

    CORS与JSONP的使用目的相同,但是比JSONP更强大。
    JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

    降域请求和postMessage()的原理

    浏览器同源政策及其规避方法

    高雪莹跨域博客

    相关文章

      网友评论

          本文标题:跨域请求

          本文链接:https://www.haomeiwen.com/subject/qkeusftx.html