一、同域发送数据

  略

二、跨域发送数据

  1、存在的问题

    1、什么是同源策略

      同源策略阻止从一个域名上加载的脚本获取或操作另一个域名上的文档属性。也就是说,受到请求的 URL 的域名必须与当前 Web 页面的域名相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。这个浏览器策略很旧,从 Netscape Navigator 2.0 版本开始就存在。

    2、ajax跨域发送数据受到浏览器同源策略的影响,当ajax向其他域名发送数据时,其他域名服务器正常处理该请求并且返回数据给ajax,但是客户端浏览器会检测到该数据是跨域请求的数据,然后就组织该数据的接收(即ajax跨域发送数据,服务端正常返回数据,客户端判断跨域发送阻止数据接受)。

  2、解决方法原理

     1、原理1:前端发送数据虽然ajax受同源策略限制。但是前端<script>、<img>、<iframe>等节点元素发送数据不受同源策略限制(凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>)。ajax可以仿照前端script节点元素发送数据从而绕过浏览器同源策略限制,即jsonp方法(绕过策略,后们进入)。

     2、原理2:前端向异域名发送ajax数据之所以不能接受到数据是由于收浏览器的同源策略影响,所以我们可以通过代理的方式来让代理帮我们发送数据到服务端,并且让代理帮我们接收服务端数据,因为代理上接受和发送数据不是通过浏览器进行发送接受的,所以不会受同源策略的影响。比如说python中的requests模块是专门仿造浏览器发送和接受请求的。

     3、原理3:前端发送ajax数据之所以受同源策略限制是因为服务端返回数据没有设置响应头,浏览器通过判断响应头来是否接受数据,所以我们就可以在服务端发送数据之前设置好响应头信息,即CORS方法

  3、解决方法

     1、script方法(客户端根据script元素标签属性自动生成jsonp方法)

       1、须知<script>、<img>、<iframe>中的src属性都是通过get方式将请求的数据下载下来(下载的数据是字符串形式的变量),然后通过本地的js渲染下载的数据,就和服务端中数据一摸一样。

        eg:客户端设置代码(客户端代码必须是在html头中先定义相对应的函数,然后再访问域名)

<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function fun(arg) {
alert(arg)
}
</script>
<script src="http://127.0.0.1:8000/get_data.html"></script> </head>

        服务端设置代码(服务端是直接返回一个带有客户端函数名称的字符串,说白了就是要符合js语法的字符串)

def get_data(request):

    return HttpResponse('fun("机密数据")')

      2、input方法(客户端根据input元素标签属性手动生成jsonp方法)

        eg:客户端设置代码(客户端代码在html的body中设置一个onclick事件,只要一触发就在在html头中添加script标签然后执行相应的函数)

<body>
<h1>皇家赌场</h1>
<input type="text" />
<div id="i1"></div>
<input type="button" onclick="jsonp('http://127.0.0.1:8000/get_data.html')" value="发送JSONP请求"/>
<script src="/static/jquery-3.2.1.js"></script>
<script>
function fun(arg) {
alert(arg); document.head.removeChild(tag);
} function jsonp(url){
tag = document.createElement('script');
tag.src = url;
document.head.appendChild(tag);
}
</script>

        服务端同1

      3、input方法+url方法(客户端根据url传递的相应参数使服务端返回相对应的字符串)

        eg:客户端设置代码(客户端代码设置与方法2雷同,但是在url路径上加入了相应的参数)

<body>
<h1>皇家赌场</h1>
<input type="text" />
<div id="i1"></div> <input type="button" onclick="jsonp('http://127.0.0.1:8000/get_data.html?callback=funcvvvvvv')" value="发送JSONP请求"/>
<script src="/static/jquery-3.2.1.js"></script>
<script>
function funcvvvvvv(arg) {
alert(arg); document.head.removeChild(tag);
} function jsonp(url){
tag = document.createElement('script');
tag.src = url;
document.head.appendChild(tag);
}
</script>

        服务端代码设置(根据客户端传递过来的值返回相应的字符串给客户端)

def get_data(request):
func_name = request.GET.get('callback')
return HttpResponse('%s("机密数据")' %func_name)

      注释:以上三种方法不是通过ajax方式发送的数据,不受同源策略的限制

      4、jsonp方法

        eg:客户端代码(客户端通过jsonp方式发送ajax实际上不是发送ajax请求,而是把ajax内的数据转换成script标签和相应的函数,根据script标签属性来发送数据)

<body>
<h1>皇家赌场</h1>
<input type="text"/>
<div id="i1"></div> <input type="button" onclick="Jsonp2()" value="发送JSONP2请求"/> <script src="/static/jquery-3.2.1.js"></script>
<script>
function Jsonp2() {
$.ajax({
url: "http://127.0.0.1:8000/get_data.html",
type: 'GET',
dataType: 'JSONP',
success: function (data) {
alert(data);
}
})
}
</script>

        服务端代码()jQuery32107032112019471077_1508251792310

def get_data(request):
func_name = request.GET.get('callback')
return HttpResponse('%s("机密数据")' %func_name)

     5、jsonp完整版

        eg:客户端代码(dataType告诉ajax我其实是通过生成script标签发送数据,jsonp实际上是向url上添加一个键值对来告诉客户端返回的字符串的格式,jsonpCallback实际上是客户端接受到数据后执行对应的函数)

<body>
<h1>皇家赌场</h1>
<input type="button" onclick="Jsonp3()" value="发送JSONP3请求"/> <script src="/static/jquery-3.2.1.js"></script>
<script>
function Jsonp3() {
$.ajax({
url: "http://127.0.0.1:8000/get_data.html",
type: 'GET',
dataType: 'JSONP',
jsonp: 'callback',
jsonpCallback: 'list'
})
}
function list(arg) {
console.log(arg)
alert(arg)
} </script>
</body>

      eg:服务端代码

def get_data(request):
func_name = request.GET.get('callback')
return HttpResponse('%s("机密数据")' %func_name)

    2、代理方法

      在python中可以通过requests模块来实现代理

    3、CORS方法(之前已经讲了cors方法主要是在服务器端设置返回的响应头信息)

      1、在客户端设置代码(直接通过ajax发送数据)

<body>
<h1>皇家赌场</h1>
<script src="/static/jquery-3.2.1.js"></script>
<script>
$.ajax({
url: "http://127.0.0.1:8000/get_data.html?xxx=666",
type: 'GET',
success: function(data){
console.log(data);
}
})
</script>
</body>

      2、在服务端局部设置响应头(*代表匹配所有,也可以跟正则表达式匹配)

def get_data(request):
response = HttpResponse("机密数据")
response['Access-Control-Allow-Origin'] = "*"
# response['Access-Control-Allow-Origin'] = "http://127.0.0.1:8000"
return response

      3、如果想在全局设置响应头信息就可以直接在django中间件中设置

三、cors补充

   1、简单请求 和 非简单请求(同时满足以下两个条件时,则是简单请求,否则为复杂请求

      条件:1、请求方式:HEAD、GET、POST

         2、请求头信息:
          Accept
          Accept-Language
          Content-Language
          Last-Event-ID
          Content-Type 对应的值是以下三个中的任意一个
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain
   2、简单请求和非简单请求的区别?
     简单请求:一次请求

     非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输,"
   3、关于“预检”
     1、请求方式:OPTIONS

     2、什么是预检
        预检其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
     3、如何预检?
       1、如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
        Access-Control-Request-Method
       2、 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
        Access-Control-Request-Headers
     4、基于cors实现AJAX请求:
      1、支持跨域,简单请求(略)
      2、支持跨域,复杂请求
        由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据,所以:
          “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method  
          “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
          “预检”缓存时间,服务器设置响应头:Access-Control-Max-Age
          eg:服务端代码

def get_data(request):
if request.method == "OPTIONS":
# 预检也要有返回值,可以为空,并且允许所以用户预检,允许预检方式为PUT,运行预检头的值为xxx
response = HttpResponse()
response['Access-Control-Allow-Origin'] = "*"
# response['Access-Control-Allow-Methods'] = "PUT"
response['Access-Control-Allow-Headers'] = "xxx"
     response['Access-Control-Allow-Headers']="true"

    return response 
  elif request.method == "GET":
     response = HttpResponse("机密数据")
      response['Access-Control-Allow-Origin'] = "*"
      return response

  客户端代码

  function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'PUT',
dataType: 'text',
headers: {'k1': 'v1'},
xhrFields:{withCredentials: true},#如果设置想要头必须加上这句话
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})

      

  

ajax跨域资源共享的更多相关文章

  1. AJAX跨域资源共享 CORS 详解

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing). 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从 ...

  2. 黑马学习Ajax 跨域资源共享 jQuery+jsonp实现

  3. AJAX学习笔记2:XHR实现跨域资源共享(CORS)以及和JSONP的对比----转载

    1 前言: 首先对参考文章作者表示感谢,你们的经验总结给我们这些新手提供了太多资源.本文致力于解决AJAX的CORS问题,我在逻辑上进行了梳理:首先,系统的总结了CORS问题的起源-同源策略:其次,介 ...

  4. 跨域资源共享(CORS)--跨域ajax

    几年前,网站开发者都因为ajax的同源策略而撞了南墙.当我们惊叹于XMLHttpRequest对象跨浏览器支持所带来的巨大进步时,我们很快发现没有一个方法可以使我们用JavaScript实现请求跨域访 ...

  5. django上课笔记7-jQuery Ajax 和 原生Ajax-伪造的Ajax-三种Ajax上传文件方法-JSONP和CORS跨域资源共享

    一.jQuery Ajax 和 原生Ajax from django.conf.urls import url from django.contrib import admin from app01 ...

  6. Ajax跨域实现

    Ajax Ajax,Asynchronus JavaScript and XML,字母意思:异步的 JavaScript 和 XML,是指一种创建交互式网页应用的网页开发技术.用于异步地去获取XML作 ...

  7. Ajax跨域:jsonp还是CORS

    跨域一般用jsonp,兼容性比较好.CORS是html5最新的XHR第二版本,不支持IE8,IE9,对移动端的支持非常好.但是考虑项目后期这部分会转到同域名下,而且网址不需要支持ie8,ie9,所以我 ...

  8. PhoneGap开发跨平台移动APP - 解决跨域资源共享

    解决跨域资源共享 一.WebApi解决跨域资源共享. 开发中选择WebApi来作为服务端的数据接口,由于使用PhoneGap,就需要通过js来获取远程远程数据服务器的数据,由于同源策略的限制,这就涉及 ...

  9. [CORS:跨域资源共享] 同源策略与JSONP

    Web API普遍采用面向资源的REST架构,将浏览器最终执行上下文的JavaScript应用Web API消费者的重要组成部分."同源策略"限制了JavaScript的跨站点调用 ...

随机推荐

  1. nginx服务器部署

    nginx(“engine x”)是一个高性能的HTTP和反向代理服务器.   安装nginx Linux下  sudo apt-get install nginx windows下 下载 nginx ...

  2. AES中几种加密模式的区别:ECB、CBC、CFB、OFB、CTR

    AES: aes是基于数据块的加密方式,也就是说,每次处理的数据时一块(16字节),当数据不是16字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度 分组加密的几种 ...

  3. vue的计算属性

    在模板中写入过多的逻辑使模板过重且难以维护.因此有了计算属性(computed)的产生. 你可以像绑定普通属性一样在模板中绑定计算属性,vue知道计算属性中的函数依赖data中的数据.所以当data中 ...

  4. 设计模式中类的关系之组合关系(Composition)

    组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合:它同样体现整体与部分间的关系,但此时整体与部分是不可分的,它们具有统一的生存期,整体的生命周期结 ...

  5. FreeMarker调用Java静态方法以及静态变量的方法

    这里介绍下在类似 Spring+FreeMarker 的架构中如何在FreeMarker中访问Java中的静态方法以及静态变量. 一.首先为了方便以及可复用我们创建一个工具类 /** * FreeMa ...

  6. er图 画图工具

    http://www.oschina.net/project/tag/83/db-model

  7. Servlet 服务器 HTTP 响应

    状态行包括 HTTP 版本(在本例中为 HTTP/1.1).一个状态码(在本例中为 200)和一个对应于状态码的短消息(在本例中为 OK). 下表总结了从 Web 服务器端返回到浏览器的最有用的 HT ...

  8. Eclipse 快速修复

    Eclipse 快速修复 使用快速修复 在 Eclipse 编辑器中当你输入字母时,编辑器会对你输入的内容进行错误分析. Java 编辑器中使用 Java 语法来检测代码中的错误.当它发现错误或警告时 ...

  9. jq中prop和attr的区别以及各自的使用

    在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: ...

  10. WPF的本质:数据和行为

    如果自己来做一个UI框架,我们会首先关注哪些方面?我想UI框架主要处理的一定包括两个主要层次的内容,一个是数据展现,另一个就是数据操作,所以UI框架必须能够接收各种不同的数据并通过UI界面展现出来,然 ...