一、同域发送数据

  略

二、跨域发送数据

  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. 88. Merge Sorted Array【easy】

    88. Merge Sorted Array[easy] Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 ...

  2. grub的三种安装方式

    1.install命令 install: install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p ...

  3. Django的自定义标签

    Django提供了自定义标签功能,可以方便常用方法的重复使用. 标签的本质就是函数,标签名就是函数名. 注意点: 1.需要到django.template对象. 2.register = templa ...

  4. springboot开启事务管理

    spring中开启事务管理需要在xml配置文件中配置,springboot中采取java config的配置方式. 核心是@EnableTransactionManager注解,该注解即为开启事务管理 ...

  5. Hibernate使用Log4j日志记录(使用xml文件)

    日志记录使程序员能够将日志详细信息永久写入文件. Log4j和Logback框架可以在hibernate框架中使用来支持日志记录. 使用log4j执行日志记录有两种方法: 通过log4j.xml文件( ...

  6. python 循环内部添加多个条件判断会出现越界

    1.循环遍历数组是,想添加条件修改时,只删除第一个 # -*- coding: utf-8 -*- a=[11,22,33,44,55] for i in a: if i == 11 or i ==2 ...

  7. 关于c中volatile关键字

    一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了.精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存 ...

  8. git Staging Deleted files

    Use git rm foo to stage the file for deletion. (This will also delete the file from the file system, ...

  9. Linux 开机自动挂载分区

    参考:http://linuxso.com/linuxrumen/3658.html 参考:http://www.jb51.net/os/RedHat/213998.html 查看磁盘UUID信息 [ ...

  10. hadoop2.2集群部署教程连接

    完全分布式部署:http://blog.csdn.net/licongcong_0224/article/details/12972889 伪分布式部署:http://www.kankanews.co ...