Django入门到放弃之CSRF_TOKEN
django使用中间件:django.middleware.csrf.CsrfViewMiddleware解决csrf攻击
form表单使用:
1 | - 在form表单中 { % csrf_token % } |
ajax提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 方式一:放到data中 $.ajax({ url: '/csrf_test/' , method: 'post' , data: { 'name' : $( '[name="name"]' ).val(), 'password' : $( '[name="password"]' ).val(), 'csrfmiddlewaretoken' :$( '[name="csrfmiddlewaretoken"]' ).val() }, success: function (data) { console.log( '成功了' ) console.log(data) }, error: function (data) { console.log( 'xxxxx' ) console.log(data) } }) 方式二:放到data中 'csrfmiddlewaretoken' : '{{ csrf_token }}' 方式三:放到头中 headers:{ 'X-CSRFToken' : '{{csrf_token}}' }, |
1 2 3 4 5 6 7 8 9 10 11 | # 全局启用,局部禁用(中间件不能注释,这个视图函数,已经没有csrf校验了) @csrf_exempt def csrf_test(request): if request.method = = 'GET' : return render(request, 'csrf_test.html' ) else : name = request.POST.get( 'name' ) password = request.POST.get( 'password' ) print (name) print (password) return HttpResponse( '登录成功' ) |
1 2 3 4 5 6 7 8 9 10 | @csrf_protect def csrf_test(request): if request.method = = 'GET' : return render(request, 'csrf_test.html' ) else : name = request.POST.get( 'name' ) password = request.POST.get( 'password' ) print (name) print (password) return HttpResponse( '登录成功' ) |
1 | path( 'csrf_test/' , csrf_exempt(views.csrf_test)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | # (没有登录就可以访问:login,home, 登录后才能访问:order,userlist,logout) middlewares.py from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse,redirect class LoginAuth(MiddlewareMixin): def process_request( self , request): exclude_url = [ '/login/' ] res = request.session.get( 'is_login' ) request_path = request.get_full_path() # 如果没有登录并且访问的不是login路径,则获取之前的访问路径 if ( not res) and (request.path not in exclude_url) : login_path = reverse ( 'login' ) return redirect( '%s?returnUrl=%s' % (login_path,request_path)) # 如果已经登录并且访问的是login路径,则提示注销后再登录 elif res and (request.path in exclude_url): return HttpResponse( '您当前已经登录,请注销后重新登录' ) view.py def login(request): if request.method = = 'GET' : return render(request, 'login.html' ) else : print ( 'login函数' ) username = request.POST.get( 'username' ) password = request.POST.get( 'password' ) user_obj = models.User.objects. filter (name = username, password = password) if user_obj: request.session[ 'is_login' ] = True path = request.GET.get( 'returnUrl' ) if path: obj = redirect(path) else : obj = redirect( 'login' ) return obj else : return HttpResponse( '用户或密码错误' ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 无论前端是什么编码的请求,后端视图函数都有request.data 前端代码: get提交 urlencoded编码 <div class = "container-fluid" > <div class = "row" > <div class = "col-md-8 col-md-offset-2" > <h1 class = "text-center" >登录界面< / h1> <form action = " " method=" get"> { % csrf_token % } <div class = "form-group" > <label for = "id_username" >用户名:< / label> < input type = "text" class = "form-control" id = "id_username" placeholder = "用户名" aria - describedby = "basic-addon1" name = "username" > < / div> <div class = "form-group" > <label for = "id_password" >密码:< / label> < input type = "password" class = "form-control" id = "id_password" placeholder = "密码" aria - describedby = "basic-addon1" name = "password" > < / div> <div class = "form-group" > < input class = "btn btn-danger" type = "submit" > < / div> < / form> < / div> < / div> < / div> |
post提交 urlencoded编码
1 | 除了method为post其他和get相同 |
post提交 form-data编码 #包含文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | form表单提交 <div class = "container-fluid" > <div class = "row" > <div class = "col-md-8 col-md-offset-2" > <h1 class = "text-center" >登录界面< / h1> <form action = " " method=" post " enctype=" multipart / form - data"> #注意修改编码 { % csrf_token % } <div class = "form-group" > <label for = "id_username" >用户名:< / label> < input type = "text" class = "form-control" id = "id_username" placeholder = "用户名" aria - describedby = "basic-addon1" name = "username" > < / div> <div class = "form-group" > <label for = "id_password" >密码:< / label> < input type = "password" class = "form-control" id = "id_password" placeholder = "密码" aria - describedby = "basic-addon1" name = "password" > < / div> <div class = "form-group" > <label for = "id_file" >上传文件:< / label> < input type = "file" id = "id_file" aria - describedby = "basic-addon1" name = "file" > < / div> <div class = "form-group" > < input class = "btn btn-danger" type = "submit" > < / div> < / form> < / div> < / div> < / div> = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ajax提交 <div class = "container-fluid" > <div class = "row" > <div class = "col-md-8 col-md-offset-2" > <h1 class = "text-center" >登录界面< / h1> <form action = " " method=" post " enctype=" multipart / form - data"> { % csrf_token % } <div class = "form-group" > <label for = "id_username" >用户名:< / label> < input type = "text" class = "form-control" id = "id_username" placeholder = "用户名" aria - describedby = "basic-addon1" name = "username" > < / div> <div class = "form-group" > <label for = "id_password" >密码:< / label> < input type = "password" class = "form-control" id = "id_password" placeholder = "密码" aria - describedby = "basic-addon1" name = "password" > < / div> <div class = "form-group" > <label for = "id_file" >上传文件:< / label> < input type = "file" id = "id_file" aria - describedby = "basic-addon1" name = "file" > < / div> <div class = "form-group" > < input class = "btn btn-danger" type = "submit" > < / div> < / form> < / div> < / div> < / div> <div> <div class = "form-group" > <label for = "id_username" >用户名:< / label> < input type = "text" class = "form-control" id = "id_username" placeholder = "用户名" aria - describedby = "basic-addon1" name = "username" > < / div> <div class = "form-group" > <label for = "id_password" >密码:< / label> < input type = "password" class = "form-control" id = "id_password" placeholder = "密码" aria - describedby = "basic-addon1" name = "password" > < / div> <div class = "form-group" > <label for = "id_file" >上传文件:< / label> < input type = "file" id = "id_file" aria - describedby = "basic-addon1" name = "file" > < / div> <div class = "form-group" > < input class = "btn btn-danger" type = "button" value = "提交" id = "data_submit" > < / div> <script> $( '#data_submit' ).click(function () { var formdata = new FormData(); formdata.append( 'myfile' , $( "#id_file" )[ 0 ].files[ 0 ]); formdata.append( 'csrfmiddlewaretoken' , '{{ csrf_token }}' ); formdata.append( 'name' , $( "#id_username" ).val()); formdata.append( 'password' , $( "#id_password" ).val()); $.ajax({ url: { % url 'login' % }, method: 'post' , processData: false, contentType: false, data: formdata, success: function (response) { console.log(response) } }) }) < / div> |
post提交 json编码 使用ajax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <div class = "form-group" > <label for = "id_username" >用户名:< / label> < input type = "text" class = "form-control" id = "id_username" placeholder = "用户名" aria - describedby = "basic-addon1" name = "username" > < / div> <div class = "form-group" > <label for = "id_password" >密码:< / label> < input type = "password" class = "form-control" id = "id_password" placeholder = "密码" aria - describedby = "basic-addon1" name = "password" > < / div> <div class = "form-group" > < input class = "btn btn-danger" type = "button" value = "提交" id = "data_submit" > < / div> <script> $( '#data_submit' ).click(function () { $.ajax({ url: { % url 'login' % }, method: 'post' , contentType: 'application/json' , headers:{ 'X-CSRFToken' : '{{csrf_token}}' }, data:JSON.stringify({name:$( "#id_username" ).val(),password:$( "#id_password" ).val()}), success: function (response) { console.log(response) } }) }); < / script> |
中间件代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Data_Conv(MiddlewareMixin): def process_request( self , request): request.data = {} # get提交数据,urlencoded编码方式,把form数据转换成一个字串(name1=value1&name2=value2…) if request.method = = 'GET' and request.META.get( 'CONTENT_TYPE' ) = = 'application/x-www-form-urlencoded' : for k in request.GET: request.data[k] = request.GET[k] # post提交数据,urlencoded编码方式,把form数据封装到http body中 elif request.method = = 'POST' and request.META.get( 'CONTENT_TYPE' ) = = 'application/x-www-form-urlencoded' : for k in request.POST: request.data[k] = request.POST[k] # post提交数据,form-data编码方式,把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file), # Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary). # 需要注意的是POST中只有文件的名称,文件的数据实际保存在request.FILES中,通过 request.FILES.get('myfile').chunks()获取文件的数据 elif request.method = = 'POST' and request.META.get( 'CONTENT_TYPE' ) = = 'multipart/form-data' : for k in request.POST: request.data[k] = request.POST[k] # post提交数据,json编码方式, ajax请求中 content-type:application/json,在后台接受前台提交的数据,前端提交的数据是 json格式的字符串 elif request.method = = 'POST' and request.META.get( 'CONTENT_TYPE' ) = = 'application/json' : post_data = json.loads(request.body) for k in post_data: request.data[k] = post_data[k] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class OverTime(MiddlewareMixin): def process_request( self , request): # 获取客户端IP地址 IP = request.META.get( 'REMOTE_ADDR' ) print (IP) # 获取该IP地址的值,如果没有,给一个默认列表[] lis = request.session.get(IP, []) # 获取当前时间 curr_time = time.time() # 判断操作次数是否小于3次 if len (lis) < 3 : # 如果小于3次,添加本次操作时间 lis.append(curr_time) # 保存 request.session[IP] = lis else : # 如果本次操作时间减去第一次操作时间小于60秒,则不让其继续操作 if time.time() - lis[ 0 ] < 60 : return HttpResponse( '操作过于频繁' ) else : # 如果大于60秒则交叉复制 lis[ 0 ], lis[ 1 ], lis[ 2 ] = lis[ 1 ], lis[ 2 ], time.time() # 保存 request.session[IP] = lis |
"一劳永逸" 的话,有是有的,而 "一劳永逸" 的事却极少
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2020-08-27 Linux 五种IO模型