跨域AJAX
本篇主要讨论JSONP和CORS这两种技术,使用它们的原因是为了完成对资源的跨域访问,也就是如何绕过浏览器的同源策略Same-origin Policy。
那么什么是Same-origin Policy呢?简单地说,在一个浏览器中访问的网站不能访问另一个网站中的数据,除非这两个网站具有相同的Origin,也即是拥有相同的协议、主机地址以及端口。一旦这三项数据中有一项不同,那么该资源就将被认为是从不同的Origin得来的,进而不被允许访问。
特别的:由于同源策略是浏览器的限制,所以请求的发送和响应是可以进行,只不过浏览器不接受罢了。
浏览器同源策略并不是对所有的请求均制约:
- 制约: XmlHttpRequest
- 不叼: img、iframe、script等具有src属性的标签
解决方案:
1、-requests发请求时,跨域无限制
2、- ajax发请求时,浏览器限制【是否可以绕过限制?】
-JSONP
-CORS
requests模块当然可以通过跨域:
#####服务端(urls.py)###### urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^get_data.html/$', views.get_data),
]
######服务端(views.py)######
from django.shortcuts import render,HttpResponse def get_data(request):
return HttpResponse(‘机密文件’)
#####客户端(views.py)###### def index(request):
# 方式一:requests模块
import requests
response=requests.get("http://127.0.0.1:8000/get_data.html/")
return render(request,"index.html",{"response":response})
#####客户端(index.html)####### <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<script src="/static/jquery-3.2.1.js"></script>
</head>
<body>
<h1>JIAのHOMESITE</h1>
14{{ response.text }}
</body> 16 </html>
当然本篇主要讨论JSONP和CORS这两种跨域技术。
一、JSONP
依据:带有 src 属性的标签不受同源策略的影响(img, script, iframe等)。
我们可以通过使用 script 标签来获取内容,但 script 中 src 获取内容后,获得到的字符串(类似于调用python中的 eval 或 exec)会被 JS 执行,所以我们可以定义一个函数,然后让服务端返回的内容外面包裹一层这个函数名,前端在访问的时候把这个函数名发送过去,并提前定义好该函数。
当然,这种方法拥有一个显著的缺点,那就是只支持GET操作。
手动实现:
服务端返回的数据
from django.shortcuts import render,HttpResponse def get_data(request):
return HttpResponse('func("机密文件")')
客户端定义及获取数据
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index.html/$', views.index),
url(r'^cors.html/$', views.cors),
]
from django.shortcuts import render def index(request):
return render(request,"index.html")
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<script src="/static/jquery-3.2.1.js"></script>
</head>
<body>
<h1>JIAのHOMESITE</h1>
<input type="button" value="获取数据" onclick="getInfo()" /> <script>
var url = 'http://127.0.0.1:8000/get_data.html/'; // 服务端路径
var $script; // 模拟使用创建的标签名 function getInfo() {
$script = document.createElement('script'); // 创建一个 script 标签
$script.setAttribute('src',url); // 将需要请求数据的地址放入 script 的 src 中
document.head.appendChild($script); // 将标签放入到 head 中
} function func(data) { // 数据返回后用来接收的函数
console.log(data);
document.head.removeChild($script); // 接收完数据后,从页面删除刚才使用的标签
}
</script>
</body>
</html>
通过JSONP自动完成 - 上面是它的原理
服务端返回的数据
from django.shortcuts import render,HttpResponse def get_data(request):
# 根据后端发送过来的名字来决定返回时,数据外面套的内容
funcName = request.GET.get('callback')
return HttpResponse('%s("机密文件")'%funcName)
客户端定义及获取数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<script src="/static/jquery-3.2.1.js"></script>
</head>
<body>
<h1>JIAのHOMESITE</h1> <script>
function func(data) {
console.log(data);
} $(function () {
var url = 'http://127.0.0.1:8000/get_data.html/';
$.ajax({
url:url,
type:'GET',
dataType:'JSONP',
jsonp:'callback',
jsonpCallback:'func'
});
})
</script>
</body>
</html>
二、CORS
随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。
CORS将导致跨域访问的请求分为三种:Simple Request,Preflighted Request以及Requests with Credential。
简单请求 和 非简单请求的区别
简单请求只发送一次,直接发送数据;
非简单请求则会发送两次数据,第一次发送 opption 请求(预检),为的是查看真正的数据是否可以被接收(数据头和请求方式是否符合要求), 如果符合要求,服务端可以把内容加入到头文件中来告诉浏览器;
简单请求 和 非简单请求的判断依据
条件:
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 注意:同时满足以上两个条件时,则是简单请求,否则为非简单请求
关于预检
- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求方式,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
基于cors实现AJAX请求:
a、支持跨域,简单请求
在使用cors的时候,客户端几乎不用修改,只需要按照普通的ajax的请求方式发送;
在服务端返回数据的时候,只要在返回的时候,加上一个响应头就可以解决这个问题了
服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'
*的话,代表允许所有的请求
服务端返回的数据
from django.shortcuts import render,HttpResponse def get_data(request):
if request.method == 'GET':
response=HttpResponse('机密文件')
response['Access-Control-Allow-Origin'] = '*'
return response
客户端定义及获取数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<script src="/static/jquery-3.2.1.js"></script>
</head>
<body>
<h1>JIAのHOMESITE</h1> <script>
$(function () {
var url = 'http://127.0.0.1:8000/get_data.html/';
$.ajax({
url:url,
type:'GET',
dataType:'text',
success:function (data,statusText,xmlHttpRequest) {
console.log(data);
}
})
}) </script>
</body>
</html>
b、支持跨域,复杂请求
对于复杂请求,会先发一次预检(OPTIONS)请求,如果服务端允许,那么再发送一次正式请求(如PUT等,总之就是真正的请求)。
这个时候,我们需要在后端进行判断,如果允许用户获取数据,那么当预检(OPTIONS)过来的时候,我们需要返回允许访问的请求。
- “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
- “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
- “预检”缓存时间,服务器设置响应头:Access-Control-Max-Age
服务端返回的数据
from django.shortcuts import render, HttpResponse def get_data(request): if request.method == 'OPTIONS':
response = HttpResponse() // 返回的内容可以为空,主要需要返回请求头
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Methods'] = 'PUT' // 允许的复杂请求方式为 PUT 请求;
response['Access-Control-Allow-Headers'] = 'k1' // 复杂请求还有一种情况就是定制请求头,这种情况下,我们在返回的响应中应该设置该响应头,代表允许发送请求头的key是什么
return response if request.method == 'PUT': response = HttpResponse('机密文件') response['Access-Control-Allow-Origin'] = '*' return response
客户端定义及获取数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<script src="/static/jquery-3.2.1.js"></script>
</head>
<body>
<h1>JIAのHOMESITE</h1> <script>
$(function () {
var url = 'http://127.0.0.1:8000/get_data.html/';
$.ajax({
url:url,
type:'PUT',
dataType:'text',
headers:{'k1':'v1'},
success:function (data,statusText,xmlHttpRequest) {
console.log(data); //获取响应头
console.log(xmlHttpRequest.getAllResponseHeaders()); //Content-Type: text/html; charset=utf-8
}
})
}) </script>
</body>
</html>
如果我们不想每次都经过“预检”这个环节的话,那么我们可以在服务器的响应头中增加一组:Access-Control-Max-Age的响应头,可以写成
response['Access-Control-Allow-Headers'] = 10 // 默认单位为秒
c、跨域获取响应头
默认获取到的所有响应头只有基本信息,如果想要获取自定义的响应头,则需要在服务器端设置Access-Control-Expose-Headers。
d、跨域传输cookie
在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。
如果想要发送:
- 浏览器端:XMLHttpRequest的withCredentials为true
- 服务器端:Access-Control-Allow-Credentials为true
- 注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符 *
服务端返回的数据
from django.shortcuts import render, HttpResponse def get_data(request):
if request.method == 'OPTIONS':
response = HttpResponse()
response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8888'
response['Access-Control-Allow-Methods'] = 'PUT'
response['Access-Control-Allow-Headers'] = 'k1'
response['Access-Control-Allow-Credentials'] = 'true' #加在了这里
return response if request.method == 'PUT':
response = HttpResponse('机密文件')
response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8888'
response['Access-Control-Allow-Credentials'] = 'true' #加在了这里
return response
客户端定义及获取数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<script src="/static/jquery-3.2.1.js"></script>
</head>
<body>
<h1>JIAのHOMESITE</h1> <script>
$(function () {
var url = 'http://127.0.0.1:8000/get_data.html/';
$.ajax({
url:url,
type:'PUT',
dataType:'text',
headers:{'k1':'v1'},
xhrFields:{withCredentials:true}, //加在了这里
success:function (data,statusText,xmlHttpRequest) {
console.log(data); //获取响应头
console.log(xmlHttpRequest.getAllResponseHeaders());
}
})
}) </script>
</body>
</html>
参考博文:http://www.cnblogs.com/alwaysInMe/p/7686931.html
跨域AJAX的更多相关文章
- 跨域Ajax请求WebService方法
一.允许跨域Ajax请求,更改如下配置: 在要调用的WebService上面添加特性标签: 二.以如下返回用户信息的WebService方法为例 三.在另一个网站上通过Ajax访问webService ...
- 使用$.getJSON实现跨域ajax请求
jQuery中常用getJSON来调用并获取远程的JSON字符串,将其转换为JSON对象,如果成功,则执行回调函数.原型如下: jQuery.getJSON( url, [data], [callba ...
- 跨域Ajax请求 web.config文件配置
在web.config文件的<system.webServer>节点下面添加如下配置代码:<!--允许跨域ajax访问--> <httpProtocol> < ...
- 使用JSONP进行跨域Ajax 调用
JSONP 是啥 JSONP 全称是JSON with Padding. 当需要进行跨域Ajax 调用的时候, 需要用到JSONP 协议. 客户端 $.ajax({ url: 'http://xxx' ...
- 前端 - jsonp 跨域ajax
jsonp 跨域ajax原理: 浏览器同源策略限制 如何解决同源策略限制: 方式一: 利用创建script块,在其中执行src属性为 远程url 异域 用函数(返回值) 的形式返回参数 方式二: jq ...
- Ajax与跨域Ajax
Ajax 对于WEB应用程序:用户浏览器发送请求,服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML)渲染并显示浏览器上.对于传统的Web应用,一个简单操作需 ...
- 跨域资源共享(CORS)--跨域ajax
几年前,网站开发者都因为ajax的同源策略而撞了南墙.当我们惊叹于XMLHttpRequest对象跨浏览器支持所带来的巨大进步时,我们很快发现没有一个方法可以使我们用JavaScript实现请求跨域访 ...
- 06: AJAX全套 & jsonp跨域AJAX
目录: 1.1 AJAX介绍 1.2 jQuery AJAX(第一种) 1.3 原生ajax(第二种) 1.4 iframe“伪”AJAX(第三种) 1.5 jsonp跨域请求 1.6 在tornad ...
- 跨域Ajax -- jsonp和cors
跨域Ajax - jsonp - cors 参考博客: http://www.cnblogs.com/wupeiqi/articles/5703697.html http://www.cnblogs. ...
- 【HTTP header】【Access-Control-Allow-Credentials】跨域Ajax请求时是否带Cookie的设置
1. 无关Cookie跨域Ajax请求 客户端 以 Jquery 的 ajax 为例: $.ajax({ url : 'http://remote.domain.com/corsrequest', d ...
随机推荐
- HDU6415 Rikka with Nash Equilibrium
HDU6415 Rikka with Nash Equilibrium 找规律 + 大数 由于规律会被取模破坏,所以用了java 找出规律的思路是: 对于一个n*m的矩阵构造,我先考虑n*1的构造,很 ...
- P1970花匠
传送 首先,这道题据说是一个dp 其次,贪心就能做 我们先来看好想好写的贪心 按照题目来,所有偶数点要么都是凸的,要么都是凹的,不能有凸有凹.我们把每株花的高度都在平面直角坐标系中点出来,再连线.这样 ...
- STM32 I2C 难点---这个不错,留着慢慢研究
来自:http://bbs.ednchina.com/BLOG_ARTICLE_2154168.HTM I2C 总线在所有嵌入式系统中用得极广, 是一个工业级别的总线, 但由于STM32 是一个32位 ...
- day32—CSS多列布局学习
转行学开发,代码100天——2018-04-17 关于多列布局,前期已经梳理过,今天的培训课程学习中再次提及,趁此也做个总结和检验. 多列布局的介绍参考: day08—css布局解决方案之多列布局 ...
- Git是目前世界上最先进的分布式版本控制系统(没有之一)。
http://zhidao.baidu.com/link?url=NSYPiSvtGTMoqMA9vt68FRRF8WbfYVmwWeMh47_2lkp0K3jFMl--1Co1tg1R4VshTQV ...
- Vagrant 手册之 Multi-machine 多机器
原文地址 Vagrant 可以在一个 Vagrantfile 中定义并控制多个虚拟机.这就是"multi-machine"环境. 这些机器可以协同工作或互相关联.multi-mac ...
- JS对象—对象总结(创建、属性、方法)
1.创建对象Object 1.1 字面量的方式创建 1.2 new Object() 1.3 构造函数创建 1.4 工厂模式 1.5 Object.create() ES5新增方法 Object. ...
- JavaScript.convertArray
function convertArray(nodeList){ var arr = [] if(Array.prototype.slice){ arr = [].sl ...
- MySQL-第一篇认识MySQL
1.什么是mysql mysql是一种关系型数据库,是瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品. 2.mysql的安装 下载mysql-installer-community- ...
- 提交代码到github
1. 下载git 点击download下载即可.下载地址:https://gitforwindows.org/ 2. 注册github github地址:https://github.com/ 一定要 ...