django学习第十二天--ajax请求和csrftoken认证的三种方式
基于cookie的登录认证装饰器
def check_login(f):
def inner(request,*args,**kwargs):
is_login = request.COOKIES.get('is_login')
if is_login == 'True':
ret = f(request)
return ret
else:
return redirect('login')
return inner
@check_login
def cart(request):
return render(request,'cart.html')
基于session的登录认证装饰器
def check_login(f):
def inner(request,*args,**kwargs):
is_login = request.session.get('is_login')
if is_login:
ret = f(request,*args,**kwargs)
return ret
else:
return redirect('login')
return inner
@check_login
def cart(request):
return render(request,'cart.html')
sweetalert插件完成ajax删除数据动作
局部刷新页面进行删除 参考图书管理系统基于ajax请求删除数据
sweetalert基于bootstrap,所有首先要先导入bootstrap插件,然后把sweetalert下载下来,一般前端开发人员会把插件放在dist文件夹里面,所有我们只要用dist文件夹里面的插件就可以了,其他的都不要
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap-sweetalert-master/dist/sweetalert.css' %}"> //sweetalert插件css
</head>
<body>
<button class="btn btn-danger">删除啦</button>
</body>
<script src="{% static 'jquery.js' %}"></script>
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
<script src="{% static 'bootstrap-sweetalert-master/dist/sweetalert.min.js' %}"></script> //sweetalert插件js
</html>
$('.del').on('click',function(){
var delete_id = $(this).prev().text() //获取上一个标签的id
var ths = $(this); //因为下面的函数中this指向的不是我们的标签按钮,所以通过一个全部变量来保存一下这个$(this),方便后面使用
swal({ //这个sweetalert内部源码 直接拿来用就行,修改下文本内容
title:'are you sure?',
text:'要谨慎!',
type:'warning',
showCancalButton:true,
confirmButtonClass:'btn-danger',
confirmButtonText:'确定删除',
cancelButtonText:'容我三思',
closeOnConfirm:false
},
//点击确认删除时触发的函数
function(){
$.ajax({//路径拼接相当于/ajax_delete_book/1/
url:'/ajax_delete_book/'+delete_id+'/',
type:'get',
success:function(res){
console.log(res);
if (res==='ok'){
//关闭弹窗
swal('删除成功!','你可以准备跑路了!','success');//这个是swal自带的方法
//局部刷新,删除对应记录
ths.parent().parent().remove();
}
}
})
}
)
})
js中的箭头函数
普通函数:var k = function(参数){return 'kkk'};
箭头函数:var k =(参数) =>{return 'kkkk'};
箭头函数简写:var k = (参数) => 'kkkk'
js函数中this的指向问题,面试题
- 1.箭头函数 会去寻找上下文的this
var a = 'xx';
var d1 = {
a:'ss',
f:()=>{
//this指向函数调用者
console.log(this.a); //xx
},
}
d1.f() #调用者是d1对象,但是里面是箭头函数,所以会去往d1对象上面寻找,即window对象,所以打印的内容为xx
- 2.函数的单体模式
var a = 'xx';
var d1 = {
a:'ss',
f(){
console.log(this.a);
},
}
d1.f() #调用者是d1对象,打印结果为ss
- 3.没有对象调用,那么this指向的就是window对象
var a = 'xx';
var d1 = {
a:'ss',
f:function(){
console.log(this.a); //ss
function f1(){
console.log(this);//指向了window对象
console.log(this.a);//结果为xx
}
f1()
},
}
d1.f()
- 4.箭头函数,改变this的指向,将this指向上下文的this
var a = 'xx';
var d1 = {
a:'ss',
f:function(){
console.log(this.a); //ss
var f1 = ()=>{
console.log(this);//指向了d1对象
console.log(this.a); //结果为ss
}
f1()
},
}
d1.f()
首先d1.f(),d1对象调用f普通函数,那么里面首先会打印ss,然后f1()函数没有调用者,而且还是一个箭头函数,那么就会从上下文寻找this对象,即上一个调用者,即为d1,所以所以f1()函数里面指向的this就为d1,打印结果就为ss
- 5.嵌套箭头函数
var a = 'xx';
var d1 = {
a:'ss',
f:()=>{
console.log(this.a);//xx
var f1=()=>{
console.log(this);//指向了window对象
console.log(this.a); //结果为xx
}
f1()
},
}
d1.f()
首先d1.f()调用的是箭头函数,那么就会往上找,即为window对象,所以调用f会打印xx,然后里面又嵌套了一个箭头函数f1,所以f1也会往上找,f1->d1->window,所以f1中this的指向也是window,打印结果为xx
ajax处理请求失败和请求成功的方式
- html部分代码
$(".del").on("click", function () {
var delete_id = $(this).prev().text();
var ths = $(this); //因为下面的函数中this指向的不是我们的标签按钮,所以通过一个变量来保存一下这个$(this),方便后面使用
swal({
title: "are you sure?",
text: "要谨慎!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "确定删除",
cancelButtonText: "容我三思",
closeOnConfirm: false
},
//点击确认删除时触发的函数
function () {
$.ajax({
url:'/ajax_delete_book/'+'100'+'/',//这边暂时写死了100目的是要处理返回请求失败的结果,100对应的其实是要删除的id
type:'get',
success:function(res){
//当状态码为2xx或者3xx时才认为是请求正常成功了,会触发success对应的函数,但是当状态为4xx/5xx的时候,ajax认为此次请求是失败的会触发error属性对应的函数
if (res==='ok'){
console.log('okokok');
//关闭弹框
swal('删除成功!','你可以准备跑路了!','success');
//局部刷新,删除对应记录
ths.parent().parent().remove();
}else{
console.log('出错啦!')
}
};
error:function(res){
if (res.status===404){
swal('删除失败!',res.responseText,'error');
//res.responseText是后台响应回来的错误信息
}
}
}
})
- views视图代码
def ajax_delete_book(request,pk):
try:
models.Book.objects.get(pk=pk).delete()
except:
return HttpResponse('找不到对应的资源!!!',status=404)#将响应状态码改为404
return HttpResponse('OK')
CSRF跨站请求
- cookie执行流程
- csrf攻击流程
如何防止csrf攻击呢?我们自己的网站要防止这个事情
csrftoken机制,csrf攻击的最多的方式
django已经做好了这个机制
如下图
- django中的csrf机制
form表单通过csrftoken认证
- login.html文件
<form action='/login/' method='post'>
{% csrf_token %} //会生成一个隐藏的input标签,value属性里面放着token值,name属性值为csrfmiddlewaretoken
用户名:<input type='text' name='username'>
<input type='submit'>
</form>
{% csrf_token %}当我们使用from表单标签来发送请求时,如果需要csrftoken认证,那么必须将它写到我们的form表单标签里面,里面的任意位置。
生成的隐藏标签为:
<input type="hidden" name="csrfmiddlewaretoken" value="WVHKQeAuMS4RGqyLybryIBAfacDa1Dp7PEaB3Badv3y0fvLqydX36xAVen6z3oS4">
校验过程解释
html页面中的
{% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="WVHKQeAuMS4RGqyLybryIBAfacDa1Dp7PEaB3Badv3y0fvLqydX36xAVen6z3oS4">
cookie中的
csrftoken:CeFG6SA8Y8hcHAX5R93sxrS37v3iFFlcvX8xjfaRHjLlgFaKRbzXVnSJbGwHHqO9
注意:它们两个的token值是不相同的,这个不用管,到时发送给后台的时候,django会处理的
django会取出提交数据部分的token值和cookie中的token值进行比较:
WVHKQeAuMS4RGqyLybryIBAfacDa1Dp7PEaB3Badv3y0fvLqydX36xAVen6z3oS4 --前32位可以对后面的几位进行解密,html中的token解密出secret_key1 一个字符串
CeFG6SA8Y8hcHAX5R93sxrS37v3iFFlcvX8xjfaRHjLlgFaKRbzXVnSJbGwHHqO9 --前32位可以对后面的几位进行解密,cookie中的token解密出secret_key2 一个字符串
secret_key1 = secret_key2
说明:
token字符串的前32位是salt盐,后面是加密后的token,通过salt能解密出唯一的secret。
django会验证表单中的token和cookie中的token是否能解出同样的secret,secret一样则本次请求合法。
MIDDLEWARE = [
...
'django.middleware.csrf.CsrfViewMiddleware',
...
]
源码
def _compare_salted_tokens(request_csrf_token, csrf_token):
# Assume both arguments are sanitized -- that is, strings of
# length CSRF_TOKEN_LENGTH, all CSRF_ALLOWED_CHARS.
return constant_time_compare(
_unsalt_cipher_token(request_csrf_token),
_unsalt_cipher_token(csrf_token),
)
def _unsalt_cipher_token(token):
"""
Given a token (assumed to be a string of CSRF_ALLOWED_CHARS, of length
CSRF_TOKEN_LENGTH, and that its first half is a salt), use it to decrypt
the second half to produce the original secret.
"""
salt = token[:CSRF_SECRET_LENGTH]
token = token[CSRF_SECRET_LENGTH:]
chars = CSRF_ALLOWED_CHARS
pairs = zip((chars.index(x) for x in token), (chars.index(x) for x in salt))
secret = ''.join(chars[x - y] for x, y in pairs) # Note negative values are ok
return secret
ajax请求通过csrftoken认证三种方式
- 方式1
首先在html文件中间,写上{% csrf_token %}
{% csrf_token %}
用户名: <input type="text" id="uname" >
<button id="btn">ajax提交</button>
jquey代码
$('#btn').click(function(){
var uname = $('#uname').val();
//获取csrfmiddlewaretoken的input标签value属性对应的值
var token = $('[name="csrfmiddlewaretoken"]').val();
$.ajax({
url:'/login/',
type:'post',
//将token值放到请求数据部分,token的键必须是csrfmiddlewaretoken
data:{uname:uname,csrfmiddlewaretoken:token},
success:function(res){
console.log(res);
}
})
})
- 方式2
使用'{{ csrf_token }}'这个模板渲染标签,这样就不要我们在html页面中写{% csrf_token %}了。
$('#btn').click(function(){
var uname = $('#uname').val();
//直接就能得到csrfmiddlewaretoken的input标签value属性的值
var token= '{{ csrf_token }}';
$.ajax({
url:'/login/',
type:'post',
data:{uname:uname,csrfmiddlewaretoken:token},
success:function(res){
console.log(res);
}
})
})
- 方式3
借助js操作cookie的方法来获取到cookie中的csrftoken那个键对应的值
然后将这个值组成一个请求头,放到此次请求中
headers:{'X-CSRFToken':这个值}
这个值,通过js能够获取到,通过jquery也能获取到,我们看一下jquery如何操作cookie
操作步骤,下载与引入
jquery.cookie.js基于jquery;先引入jquery,再引入:jquery.cookie.js;下载:http://plugins.jquery.com/cookie/
<script src="{% static 'jquery.js' %}"></script> #这个要在上面
<script src="{% static 'jquery.cookie.js' %}"></script>
{% csrf_token %} //需要在html中写上{% csrf_token %}或{{ csrf_token }},不然此次获取这个html页面的时候,响应中不会有这个csrftoken的cookie的值
$('#btn').click(function(){
var uname = $('#uname').val();
//通过js获取jquery来获取cookie中的csrftoken这个键对应的token值
var token = $.cookie('csrftoken');
$.ajax({
url:'/login/',
type:'post',
//将获取到的token值放到请求头中,这个请求头键值对的键必须是'X-CSRFToken'
headers:{
'X-CSRFToken':token,
},
//django先去获取请求数据部分的token值,获取不到,就去找一个叫做X-CSRFToken请求头键值对,它的值和cookie中的csrftoken的值要相等。
data:{uname:uname,},
success:function(res){
console.log(res);
}
})
})
ajax上传文件
- html文件
用户名:<input type='text' name='username'>
密码:<input type='text' name='password'>
头像:<input type='file' name='touxiang'>
<button id='sub'>上传</button>
js部分
$('$sub').click(function(){
//ajax上传文件必须依赖于FormData对象
var formdata = new FormData();
var uname = $('[name="username"]').val();
var pwd = $('[name="password"]').val();
//获取浏览器上的文件数据方法:$('[name="touxiang"]')[0].files[0]
var file_obj = $('[name="touxiang"]')[0].files[0];
formdata.append('uname',uname)//后面取数据也是用request.POST.get('uname')
formdata.append('pwd',pwd)
formdata.append('csrfmiddlewaretoken','{{ csrf_token }}')
//request.FILES
formdata.append('touxiang',file_obj)
$.ajax({
url:'',//如果路径为空,那么使用当前页面的路径,也就是往当前路径下进行提交
type:'post',
data:formdata,
//下面的两个参数的意思是,不要对数据进行任何的预处理和加工
processData:false,
contentType:false,
success:function(res){
console.log(res);
}
})
})
- views文件
def upload(request):
if request.method == 'GET':
return render(request,'upload.html')
else:
print(request.POST)
print(request.FILES)
file_obj = request.FILES.get('touxiang')
with open(file_obj.name,'wb') as f:
for i in file_obj:
f.write(i)
//第二种写法
//默认一次返回大小为65536B,也就是64KB,最大2.5M
for chunk in file_obj.chunks():
f.write(chunk)
return HttpResponse('ok')
上传多文件 自行拓展 后续补充
- html文件
<input type='file' name='touxiang' multiple> //multiple为上传多个
django学习第十二天--ajax请求和csrftoken认证的三种方式的更多相关文章
- ios网络学习------4 UIWebView的加载本地数据的三种方式
ios网络学习------4 UIWebView的加载本地数据的三种方式 分类: IOS2014-06-27 12:56 959人阅读 评论(0) 收藏 举报 UIWebView是IOS内置的浏览器, ...
- Struts2学习(二)运行Action中方法的三种方式
1.运行execute()方法 一般的能够直接在action中书写execute,调用action时会自己主动运行此方法 2.配置method方法 在struts.xml中配置action时.写met ...
- Django框架之ORM的相关操作之多对多三种方式(五)
在之前的博客中已经讲述了使用ORM的多对多关系表,现在进行总结一下: 1.ORM自动帮助我们创建第三张表 2.手动创建第三张表,第三张表使用ForeignKey指向其他的两张表关联起来 3.手动创建第 ...
- python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)
昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...
- ajax的data传参的两种方式
ajax的data传参的两种方式 本文为转载. 1.[javascript] view plain copy /** * 订单取消 * @return {Boolean} 处理是否成功 */ func ...
- Django文件上传三种方式以及简单预览功能
主要内容: 一.文件长传的三种方式 二.简单预览功能实现 一.form表单上传 1.页面代码 <!DOCTYPE html> <html lang="en"> ...
- 【转】Spring学习---Bean配置的三种方式(XML、注解、Java类)介绍与对比
[原文]https://www.toutiao.com/i6594205115605844493/ Spring学习Bean配置的三种方式(XML.注解.Java类)介绍与对比 本文将详细介绍Spri ...
- Ajax上传数据和上传文件(三种方式)
Ajax向后端发送数据可以有三种方式:原生Ajax方式,jQuery Ajax方式,iframe+form 方式(伪造Ajax方式) <!DOCTYPE html> <html la ...
- 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...
- PHP的学习--连接MySQL的三种方式
记录一下PHP连接MySQL的三种方式. 先mock一下数据,可以执行一下sql. /*创建数据库*/ CREATE DATABASE IF NOT EXISTS `test`; /*选择数据库*/ ...
随机推荐
- [转帖]分享一个Navicat16最新版永久试用的办法
https://zhuanlan.zhihu.com/p/614621302 新建bat,就叫 navicat无限试用.bat @echo off echo Delete HKEY_CURRENT_U ...
- [转帖]自动化回归测试工具 —— AREX 上手实践
https://my.oschina.net/arextest/blog/8589156 AREX 是一款开源的自动化测试工具平台,基于 Java Agent 技术与比对技术,通过流量录制回放能力 ...
- 【图】苹果Safari 6.0停止支持Windows PC (转载)
[图]果Safari 6.0停止支持Windows PC (转载) http://bbs.tianya.cn/post-414-41510-1.shtml 2012年之后 苹果就不在开发 window ...
- MySQL in Windows安装以及异名恢复的简单过程
下载相关 建议获取最新版本的Mysql数据库 可以获取 zip 格式的安装文件 https://dev.mysql.com/downloads/mysql/ 或者获取 msi 格式的安装文件 http ...
- CentOS7最小安装注意事项
CentOS7最小安装注意事项 背景与说明 公司很多项目现在都是最小化安装的了. 自己之前为了方便都是使用GUI安装,很多地方可能都有遗漏 这里进行一下简单的安装总结, 避免以后新安装有缺失的项目 安 ...
- Nginx 按天拆分日志
https://blog.csdn.net/linpxing1/article/details/104059857 ### 关键位置 start if ($time_iso8601 ~ '(\d{4} ...
- 【第4个渗透靶机项目】 Tr0ll
每天都要加油哦! 0x00 信息搜集 首先找到一下靶机的ip,并扫描端口. 靶机和kali都是桥接. 那么先看一下kali的ifconfig信息. nmap -sn 192.168.0.0/24 ...
- 如何通过gRPC传输文件
在gRPC中,可以通过将文件分割成多个小块,然后使用流式RPC将这些小块发送到服务器来传输文件.以下是一个简单的示例,展示了如何在gRPC中实现文件传输. 首先,我们需要定义一个服务来处理文件传输.在 ...
- gRPC基本教程
原文在这里. 本教程为Go程序员提供了使用gRPC的基本介绍. 通过跟随本示例,你将学会如何: 在.proto文件中定义一个服务. 使用协议缓冲编译器生成服务器和客户端代码. 使用Go gRPC AP ...
- LyScript 验证PE程序开启的保护
有些漏洞利用代码需要在某个保护模式被关闭的情况下才可以利用成功,在此之前需要得到程序开启了何种保护方式.验证其实有很多方法,其原理是读入PE文件头部结构,找到OPTIONAL_HEADER.DllCh ...