跨域请求

什么是同源策略

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

同源的条件

  • 同协议:比如都是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

原理:就是利用
并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。
第三方产生的响应为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()的原理

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

高雪莹跨域博客

你可能感兴趣的:(跨域请求)