day86---django的跨域请求
1. serialize()函数
serialize()函数说明
-
serialize()函数用于序列化一组表单元素,将表单内容编码为用于提交的字符串
-
serialize()函数常用于将表单内容序列化,以便用于AJAX提交
-
serialize()函数主要根据用于提交的有效表单控件的name和value,将它们拼接为一个可直接用于表单提交的文本字符串,该字符串已经过标准的URL编码处理(字符集编码为UTF-8)
-
serialize()函数不会序列化不需要提交的表单控件,这和常规的表单提交行为是一致的
-
serialize()函数与常规表单提交不一样的是:常规表单一般会提交带有name的按钮控件,而serialize()函数不会序列化带有name的按钮控件
-
serialize()函数通常用于将表单内容序列化,以便通过AJAX方式提交
serialize()函数的语法
jQueryObject.serialize()
serialize()函数的返回值
serialize()函数的返回值为String类型,返回将表单元素编码后的可用于表单提交的文本字符串。serialize()函数即可以直接序列化所有表单元素,也可以直接对部分表单元素进行序列化
2. FormData对象
FormData介绍
利用 FormData对象,可以通过JavaScript键值对来模拟一系列表单控件,还可以使用XMLHttpRequest的send()方法来异步提交表单,与普通的Ajax相比,使用FormData的最大优点就是可以异步上传二进制文件
通过new关键字创建一个空的FormData对象,然后使用append()方法向该对象里添加字段(字段的值可以是一个Blob对象、File对象或者字符串,其他类型的值会被自动转换成字符串
Ajax(FormData)
<!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">
<script src="/static/js/jquery-3.2.1.min.js"></script>
<title>注册页面</title>
</head>
<body>
<h3>Ajax(FormData)上传文件</h3>
<p><input type="text" name="username" id="username" placeholder="username"></p>
<p><input type="file" name="upload_file_ajax" id="upload_file_ajax"></p>
<input text="button" id="upload_button" value="提交">
<script>
$("#upload_button").click(function(){
var username = $("#username").val();
var upload_file = $("#upload_file_ajax")[0].files[0];
var formData = new FormData();
formData.append("username",username);
formData.append("upload_file_ajax",upload_file);
$.ajax({
url: "/upload_file/",
type: "POST",
data: formData,
contentType: false,
processData: false,
success:function(data){
alert(data)
}
});
})
</script>
</body>
</html>
from django.shortcuts import render, HttpResponse
def index(request):
return render(request,"index.html")
def upload_file(request):
return HttpResponse("上传成功!")
伪造Ajax上传文件
<iframe>标签规定一个内联框架
一个内联框架被用来在当前HTML文档中嵌入另一个文档
<h3>伪造Ajax上传文件</h3>
<form action="/upload_file/" method="post" id="form" target="ifr" enctype="multipart/form-data">
<p><iframe name="ifr" id="ifr"></iframe></p>
<p><input type="file" name="upload_file"></p>
<p><input type="text" name="user"></p>
<input type="button" id="upload_button" value="提交">
</form>
<script>
$("#upload_button").click(function(){
$("#ifr").load(iframeLoaded);
$("#form").submit();
});
function iframeLoaded(){
alert(上传成功!)
}
</script>
from django.shortcuts import render, HttpResponse
def index(request):
return render(request,"index.html")
def upload_file(request):
return HttpResponse("上传成功!")
3. 同源策略
同源是指:域名、协议、端口相同
同源策略(Same origin policy)由Netscape提出的一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现
浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。如果是非同源访问,在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问
由于同源策略是浏览器的限制,所以请求的发送和响应是可以正常进行,只是浏览器拒绝掉了
浏览器同源策略并不是对所有的请求制约:
-
制约:XmlHttpRequest
-
不制约:img、iframe、script等具有src属性的标签
非同源时浏览器控制台拒绝访问的异常:
已拦截跨源请求:同源策略禁止读取位于http://127.0.0.1:8000/xxxx/的远程资源。(原因:CORS头缺少'Access-Control-Allow-Origin')
4. JSONP
跨域的定义:跨域名访问(当前域名向其他域名发送的请求)
原理:JSONP(JSON with Padding),是JSON的一种使用模式,利用script标签的src属性(浏览器允许script标签跨域)
JSONP约定只能发GET请求
5. CORS
简介
CORS需要浏览器和服务器同时支持。目前所有浏览器都支持该功能,IE浏览器不能低于IE10
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉
实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨源通信
两种方式
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request),浏览器对这两种请求的处理也是不一样的
(1)请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
-
只要同时满足以下两大条件,就属于简单请求(一次请求)
-
不同时满足上面两个条件,就属于非简单请求(两次请求,在发送数据之前会先发一次请求用于做'预检',只有'预检'通过后才再发送一次请求用于数据传输)
6. 对JSONP实现的应用
模拟两个项目
# 项目一
#
# views.py
from django.shortcuts import render, HttpResponse
def index(request):
return render(request, 'index.html')
def ajax_send(request):
if request.is_ajax():
user = request.GET.get('user')
pwd = request.GET.get('pwd')
print(user, pwd)
return HttpResponse('server1 is OK !!!')
#
# 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">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<title>index</title>
</head>
<body>
<h3>server1(127.0.0.1:8001)</h3>
<input type="button" id="ajax_send" value="请点击">
<script>
$("#ajax_send").click(function () {
$.ajax({
url: "http://127.0.0.1:8002/ajax_send/",
data: {
"csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
"user": 'yy1',
"pwd": '123'
},
success: function (data) {
console.log(data)
}
})
})
</script>
</body>
</html>
# 项目二
#
# views.py
from django.shortcuts import render, HttpResponse
def index(request):
return render(request, 'index.html')
def ajax_send(request):
user = request.GET.get('user')
pwd = request.GET.get('pwd')
print(user, pwd)
return HttpResponse('server2 is OK!!!')
#
# 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">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<title>index</title>
</head>
<body>
<h3>server2(127.0.0.1:8002)</h3>
<input type="button" id="ajax_send" value="请点击">
<script>
$("#ajax_send").click(function () {
$.ajax({
url: '/ajax_send/',
data: {
"csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
"user": 'yy2',
"pwd": '456'
},
success: function (data) {
console.log(data)
}
})
})
</script>
</body>
</html>
跨域请求后的报错信息
点击项目一的button按钮(项目一请求项目二的/ajax_send/)
Failed to load http://127.0.0.1:8002/ajax_send/?user=yy1&pwd=123: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8001' is therefore not allowed access.
解释:浏览器的同源策略的原因,AJax无法发送跨域请求
javascript对JSONP的实现
创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调
# 项目一
<script>
function foo(data){
console.log(data)
}
function domain(url) {
var $eleScript = $("<script>");
$eleScript.attr("src", url);
$eleScript.attr("id", "domain");
$("body").append($eleScript);
$("#domain").remove()
}
$("#ajax_send").click(function () {
domain("http://127.0.0.1:8002/ajax_send?callback=foo")
})
</script>
# 项目二
def ajax_send(request):
callback = request.GET.get('callback')
return HttpResponse("%s('server2...')" % callback)
基于jquery的getJSON方法对JSONP的实现
方法格式:$.getJSON(url,[data],[callback])
$("#ajax_send").click(function () {
$.getJSON("http://127.0.0.1:8002/ajax_send/?callback=?", function (data) {
console.log(data)
})
})
基于jquery的$.ajax对JSONP的实现
$("#ajax_send").click(function () {
$.ajax({
url: "http://127.0.0.1:8002/ajax_send",
dataType: 'jsonp',
jsonp: 'callback',
success: function (data) {
console.log(data)
}
})
})

浙公网安备 33010602011771号