70 ajax crsf插件 formdata对象.文件上传, 注册, 登录
主要内容:https://www.cnblogs.com/maple-shaw/articles/9524153.html
1 csrf中间件: csrf跨站请求伪造
a : crsf的两个静态方法:
csrf_exempt : 给单个视图排除校验
csrf_protect: 给单个视图必须校验
from django.views.decorators.csrf import csrf_exempt, csrf_protect
# 可以通过csrf校验, 不注销csrf插件的情况下
# @csrf_exempt
# def login(request):
# return render(request, 'login.html')
# 给csrf设置了一层安全保证, 不允许通过
@csrf_protect
def login(request):
return render(request, 'login.html')
b : csrf的请求流程:
从process_request方法: 从请求的cookie中获取csrf_token ——》csrf_token ——》request.META['CSRF_COOKIE']
从process_view方法:
1: 如果视图函数加上了csrf_exempt的装饰器,则不做校验
2 : 如果请求方式是'GET', 'HEAD', 'OPTIONS', 'TRACE' 也不做校验
3 : 其他的方式做校验:
request.META.get('CSRF_COOKIE') —— 》 csrf_token
request_csrf_token = ''
# 从request.POST中获取csrfmiddlewaretoken对应的值
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
# 从请求头中获取X-csrftoken 的值
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
request_csrf_token 和 csrf_token 做对比
如果校验成功 正常走
如果校验不成功 拒绝
2 浏览器向服务器发请求的方式
a : 地址栏上输入地址 回车, get请求
b : form表单提交数据, 点击submit, post请求
c : a标签
d : ajax
3 JSON内容的复习:
在JavaScript中: 关于json对象和字符串转换的两个方法:
JSON.parse(): 用于将一个json字符串转为JavaScript对象
JSON.stringify(): 用于将JavaScript的值转换为json字符串
4 ajax : 一个与服务器进行交互的技术
a : 简介: 异步的JavaScript和XML, 即使用JavaScript语言与服务器进行异步交互, 传输的数据为XML,(也不只是xml), 不是一种新的编程语言, 而是一种使用现有的标准的新方法.
b : 优点
1 : 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
2 : 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求
总结:
AJAX使用JavaScript技术向服务器发送异步请求;
AJAX请求无须刷新整个页面;
因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;
c : 实例: 页面输入两个整数, 通过ajax传输到后端进行计算出结果,返回.
url中的代码:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^calc/', views.calc),
url(r'^calcs/', views.calcs),
]
views中的代码:
from django.shortcuts import render, HttpResponse
def index(request):
i1, i2, i3 = '', '', ''
if request.method == 'POST':
i1 = int(request.POST.get('i1'))
i2 = int(request.POST.get('i2'))
i3 = i1 + i2
return render(request, 'index.html', {'i1':i1, 'i2': i2, 'i3': i3})
import time
def calc(request):
print(request.POST)
i1 = int(request.POST.get('i1'))
i2 = int(request.POST.get('i2'))
i3 = i1 + i2
time.sleep(5)
return HttpResponse(i3)
def calcs(request):
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
i3 = i1 + i2
return HttpResponse(i3)
html中的代码
<body>
<input type="text" name="i1">+
<input type="text" name="i2" >=
<input type="text" name="i3">
<button id="b1">计算</button>
<hr>
<input type="text" name="ii1">+
<input type="text" name="ii2" >=
<input type="text" name="ii3">
<button id="b2">计算</button>
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
$('#b1').click(function () {
$.ajax({
url:'/calc/',
type:'post',
data:{
i1 : $('[name="i1"]').val(),
i2 : $('[name="i2"]').val(),
},
success:function (ret) {
console.log(ret);
$('[name="i3"]').val(ret)
}
})
});
$('#b2').click(function () {
$.ajax({
url:'/calcs/',
type:'post',
data:{
i1 : $('[name="ii1"]').val(),
i2 : $('[name="ii2"]').val(),
},
success:function (ret) {
console.log(ret);
$('[name="ii3"]').val(ret)
}
})
});
</script>
</body>
</html>
d : ajax发post请求, 通过csrf验证的三种方法:
1: 页面中使用{% csrf_token%}
$('#b1').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
data: {
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val(), # **********
name: 'alex',
age: '73',
},
success: function (res) {
console.log(res);
}
})
});
2 : 通过获取返回的cookie中的字符串 放置在请求头中发送。
$('#b1').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
headers: {"X-CSRFToken": $('[name="csrfmiddlewaretoken"]').val()},
data: {
name: 'alex',
age: '73',
},
success: function (res) {
console.log(res);
}
})
});
结论 : 由于每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。
3 全局设置:
注意: 使用$.ajaxSetup()方法为ajax请求统一设置. 此时需要建一个js文件, 把下面的代码粘进去就可以.
function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
从cookie中取值, 必须有cookie
有cookie的两种方式:
1 使用{%csrf_token%};
2 from django.views.decorators.csrf import ensure_csrf_cookie
这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。
$('#b2').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
data: {},
success: function (res) {
console.log(res);
}
})
});
4 三种方法的views的代码:
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def csrf_test(request):
if request.method == 'POST':
print(request.POST)
return HttpResponse('测试成功')
return render(request, 'csrf_test.html')
5 利用ajax实现文件上传
FormData对象: 可以把所有表单元素的name与value组成一个queryString,提交到后台。 在使用ajax提交时,使用FormData对象可以减少拼接queryString的工作量
创建一个FormData空对象,然后使用append方法添加key/value:
formData.append('f1', $('#f1')[0].files[0]); # 由于jquery获取的对象是列表形式, 取出索引获取一个dom对象, .files获取文件列表, 取索引获取该文件
文件上传操作的代码:
<body>
{% csrf_token %}
<input type="file" id="f1">
<button type="button" id="b1">上传</button>
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
$('#b1').click(function () {
var formData = new FormData();
formData.append('csrfmiddlewaretoken',$('[name="csrfmiddlewaretoken"]').val());
{#FormData添加文件类型数据#}
formData.append('f1', $('#f1')[0].files[0]);
$.ajax({
url:'/upload/',
type:'post',
data:formData,
processData:false,
contentType:false,
success:function (ret) {
console.log(ret)
}
})
})
</script>
views的内容:
def upload(request):
if request.method == 'POST':
print(request.FILES)
fileobj = request.FILES.get('f1')
with open(fileobj.name, mode='wb') as f: fileobj有name属性.
# chunks一点一点的读
for i in fileobj.chunks():
f.write(i)
return HttpResponse('ok')
return render(request, 'upload.html')
6 注册: 涉及到的内容, jquery绑定事件, ajax中没有$(this)方法
html中的内容:
<body>
<input type="text" id="t1" name="user"><span id="s1" style="color:red;"></span>
{#<button id="b1">注册</button>#}
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
$('#t1').blur(function () {
{#console.log($(this));#}
_this = $(this);
{#由于ajax中没有$(this)这个方法,所以设置了一个全局变量#}
$.ajax({
url:'/reg/',
type:'post',
data:{
user:$('#t1').val()
},
success:function (res) {
console.log(res);
{#$('#s1').text(res)#}
_this.next().text(res)
}
})
}).focus(function () {
_this.next().text('')
})
</script>
views中的代码:
def reg(request):
if request.method == 'POST':
print(request.POST)
user = request.POST.get('user')
# 从数据库中找到对象
obj = models.User.objects.filter(user=user).first()
if obj:
return HttpResponse('该用户名已存在')
else:
return HttpResponse('该用户名可以使用')
return render(request, 'reg.html')
7 登录: 涉及到的内容 location.href = ''
html中的代码:
<body>
<input type="text" name="user" id="t1">
<input type="password" name="pwd" id="p1">
<button id="b1">登录</button>
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
$('#b1').click(function () {
$.ajax({
url:'/login/',
type:'post',
data: {
user: $('#t1').val(),
pwd: $('#p1').val()
},
success: function (res) {
console.log(res);
if(res.status == '0'){
location.href = res.url
}
else{
alert(res.msg)}}
})
})
</script>
</body>
views中的代码:
# 登录
from django.http import JsonResponse
def login(request):
# 从ajax中的post方法中提交的数据中取出user和pwd
if request.method == 'POST':
ret = {'status': '0', 'msg': ''}
user = request.POST.get('user')
pwd = request.POST.get('pwd')
# 数据库中找到对应的对象:
obj = models.User.objects.filter(user=user, pwd=pwd)
if obj:
ret['url'] = '/upload/'
return JsonResponse(ret)
# 如果该对象存在, 返回登录成功
else:
ret['status'] = '1'
ret['msg'] = '用户名或者是密码错误'
return JsonResponse(ret)
# 如果不存在, 返回用户名或者是密码错误.
return render(request, 'login.html')

浙公网安备 33010602011771号