Ajax(jquery)
一.AJAX简介
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数 AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。 a.同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求; b.异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。 AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程 总体来说:AJAX两个特点:异步请求和局部刷新
在js+Ajax中,要区别版本信息,在jquery中不需要。
二.AJAX使用
Ajax用jquery实现主要有三个API:$.ajax()/$.get()/$.post()
1.$.ajax()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> $.ajax({ url:"/xx/", data:{a:1,b:2}, type:"POST", processDate:false, //data数据不进行转码(默认是true,是进行转码的) traditional:true, //如果data数据中还有其他迭代:data:{a:1,b:[3,4]},传给服务端的数据为{'a':['1'],'b[]':['3','4']},traditional:true是改变这种情况,{'a':['1'],'b':['3','4'] success:function(data){ //回调函数:当某个动作完成后会自动触发的一个函数(在这里是等浏览器服务端交互完成后接受服务端发来的信息) console.log(data); console.log(arguments); //打印函数的参数 } }); $.ajax({ url:'/xx/', data:$("#f1").seralize(),//发送所有能提交的数据 traditional:true //如果是多选框,要加上这句 }) </script> </body> </html>
2.$.get()
$.get("/xx/",function(data){ //data是服务端Httpresponse返回的对象,此为回调函数 console.log(data) });
3.$.post()
$.post(url, [data], [callback], [type]) //type: text/html/json/script type指定什么类型,如果接受到服务端的数据类型不对,那么回调函数不执行
$.post("/xx/",{name:"高玉坤"},function(data,contentType,jqy){ //参数四type:用来查看返回的是否是指定类型,如果不是则不执行回调函数 console.log(arguments); console.log(data); //高玉坤 console.log(contentType); //success/err console.log(jqy); // });
4.$.getJSON()
$.get()的最后一个type参数必须是json类型
5.$.getScript() #引用另一个js文件中的某种方法
$.getScript("/xx.js/",function(){ alert(add(1,3)) ; }) ###xx.js### function add(x,y){ return x+y; }
三.AJAX请求设置csrf_token
在ajax设置csrf_token之前,我们先了解一下csrf攻击及其基本原理。
简单了解:
django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token。 token字符串的前32位是salt, 后面是加密后的token, 通过salt能解密出唯一的secret。检验token时,只比较secret是否和cookie中的secret值一样,而不是比较整个token
django会验证表单中的token(form表单中的{%csrf_token%}会生成一个隐藏的input标签:<input type="hidden" name="csrfmiddlewaretoken" value="WncCS9HKnajyZkHWnBesEeOnEW8VPiMRnTQqr1Ua1e1PSqhdhlE07VcCr4lVjTPo">)和cookie中token是否能解出同样的secret,secret一样则本次请求合法。
1.CSRF攻击原理及防范
CSRF 全拼为 Cross Site Request Forgery, 跨站请求伪造.CSRF指的是攻击者盗用了你的身份,以你的名义发送恶意的请求,给你造成个人隐私泄露及财产安全.
CSRF攻击原理
①用户正常登录A银行网站, ②A网站返回cookie信息给用户,浏览器保存cookie信息 ③在A网站没有退出登录的情况下(或者说cookie信息没过期), 登录了恶意网站B ④恶意网站B,提前准备好转账表单或者其它请求 ,将其隐藏. 把提交到A网站的按钮设置为一个"领取优惠券"的图片链接.用户 点击链接 ⑤在用户主观未知的情况下,访问A网站,此时浏览器会自动携带cookie信息 ⑥A网站识别到cookie信息,默认为是用户本人做出的请求,根据请求做出相应的操作. ⑦用户收到损失.
CSRF如何防范
在请求参数中加入一个混淆字符串csrf_token. 简单来说,服务器在接受到请求后, 返回给用户两个csrf_token值, 一个放在cookie信息中,浏览器会保存,下次请求的时候浏览器自动携带. 一个放在前端页面中(例如:表单域或者ajax的请求头中), 当用户再次向服务器发送数据的时候, 服务器会对比cookie中和前端页面中的csrf_token值,如果一样,证明是用户操作,如果不一样,证明是非法操作. 恶意网站B因为页面是提前写好的,无法获取到csrf_token值(cookie同源策略),所以服务器接受到请求的时候,会显示非法操作,从而保证了用户个人信息的安全.解决了csrf攻击
2.AJAX请求设置csrf_token
方式一:
在data中添加键值对:csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="{% static 'js/jquery-3.4.1.min.js' %}"></script> </head> <body> <form action=""> {% csrf_token %} //生成隐藏的input标签<input type="hidden" name="csrfmiddlewaretoken" value="WncCS9HKnajyZkHWnBesEeOnEW8VPiMRnTQqr1Ua1e1PSqhdhlE07VcCr4lVjTPo"> <input type="text" id="username" name="username"> <input type="password" id="password" name="password"> <input type="button" value="提交" id="submit"> </form> <script> $("#submit").click(function () { $.ajax({ url:"/test/", type:"post", data:{ username:$("#username").val(), password:$("#password").val(), csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), //取出{%csrf_token%}生成的input标签的val值 }, success:function (data) { alert(data); } }) }); </script> </body> </html>
方式二:和方式一类似
$.ajax({ data: {csrfmiddlewaretoken: '{{ csrf_token }}' }, });
方式三:
通过获取返回的cookie的字符串放置在请求头中发送
注意:需要引入jquery.cookie.js的插件
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="{% static 'js/jquery-3.4.1.min.js' %}"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.3.1/jquery.cookie.js"></script> </head> <body> <form action=""> {% csrf_token %} <input type="text" id="username" name="username"> <input type="password" id="password" name="password"> <input type="button" value="提交" id="submit"> </form> <script> $("#submit").click(function () { $.ajax({ headers:{"X-CSRFToken":$.cookie('csrftoken')}, url:"/test/", type:"post", data:{ username:$("#username").val(), password:$("#password").val(), }, success:function (data) { alert(data); } }) }); </script> </body> </html>
四.文件上传
1.form表单文件上传
html中form表单必须写enctype="multipart/form-data"
<form action="/file_test/" method="post" enctype="multipart/form-data"> //enctype必须写 <input type="file" id="file" name="file"> <input type="submit" id="submit"> </form>
views.py
def file_test(req): if req.method == "GET": return render(req,"file.html") else: file = req.FILES.get("file") #通过req.FILES.get("file")得到文件对象 with open(file.name, 'wb') as f: for chunk in file.chunks(): f.write(chunk) return HttpResponse("OK")
2.ajax文件上传
html文件中new FormData()对象。
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="{% static 'js/jquery-3.4.1.min.js' %}"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.3.1/jquery.cookie.js"></script> </head> <body> <form action=""> {% csrf_token %} <input type="file" id="file" name="file"> <input type="text" id="username" name="username"> <input type="submit" id="submit"> </form> <script> $("#submit").click(function () { var formdata = new FormData(); //新建FormData()对象 formdata.append("username",$("#username").val()); //给FormData对象添加键值对 formdata.append("file",$("#file")[0].files) formdata.append("file",$("#file")[0].files[0]); //获取第一个文件对象 $.ajax({ headers:{"X-CSRFToken":$.cookie('csrftoken')}, url:"/file_test/", type:"post", data:formdata, //将formdata对象传给后端 processData:false, //必写 contentType:false, //必写 success:function (data) { alert(data); } }) }); </script> </body> </html>
views.py写法和form表单提交一样
def file_test(req): if req.method == "GET": return render(req,"file.html") else: username = req.POST.get("username") file = req.FILES.get("file") with open(file.name, 'wb') as f: for chunk in file.chunks(): f.write(chunk) return HttpResponse("OK")
五.AJAX和Django基于json交互
数据类型转换图解:
1.最原始方法
ajax通过JSON.parse()或JSON.stringfiy()转换,django通过json.dumps()和json.loads()转换
views.py
def json_test(req): if req.method == "GET": return render(req,"json_test.html") else: dic = {"user":"root","pwd":123,"name":"急急急"} dic = json.dumps(dic,ensure_ascii=True) return HttpResponse(dic)
html中
<script> $("#submit").click(function () { $.ajax({ headers:{"X-CSRFToken":$.cookie('csrftoken')}, url:"/json_test/", type:"post", data:{"f":"f"}, success:function (data) { data = JSON.parse(data); console.log(data); console.log(typeof data); //object对象 } }) }); </script>
2.在django中设置content_type='application/json'
通过设置content_type='application/json',ajax得到的数据不用再进行parse转换
views.py
def json_test(req): if req.method == "GET": return render(req,"json_test.html") else: dic = {"user":"root","pwd":123,"name":"急急急"} dic = json.dumps(dic,ensure_ascii=True) return HttpResponse(dic,content_type='application/json')
html中
<script> $("#submit").click(function () { $.ajax({ headers:{"X-CSRFToken":$.cookie('csrftoken')}, url:"/json_test/", type:"post", data:{"f":"f"}, success:function (data) { console.log(data); console.log(typeof data); //object对象 } }) }); </script>
3.JsonResponse
views.py
非字典类型的JsonResponse(retdata,safe=False)
from django.http import JsonResponse def json_test(req): if req.method == "GET": return render(req,"json_test.html") else: dic = {"user":"root","pwd":123,"name":"急急急"} # dic = json.dumps(dic,ensure_ascii=True) # return HttpResponse(dic,content_type='application/json') return JsonResponse(dic) #相当于上述两行代码
html中
<script> $("#submit").click(function () { $.ajax({ headers:{"X-CSRFToken":$.cookie('csrftoken')}, url:"/json_test/", type:"post", data:{"f":"f"}, success:function (data) { console.log(data); //不用进行转换 console.log(typeof data); //直接得到object对象 } }) }); </script>