1.django解决csrf攻击方法
django使用中间件:django.middleware.csrf.CsrfViewMiddleware解决csrf攻击
form表单使用:
-在form表单中 {% csrf_token%}
ajax提交
方式一:放到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}}'},
2.全局使用,局部禁csrf
# 全局启用,局部禁用(中间件不能注释,这个视图函数,已经没有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('登录成功')
3.全局禁用,局部使用csrf
@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('登录成功')
古怪的使用方式,在urls.py中
path('csrf_test/', csrf_exempt(views.csrf_test))
5.代码示例
登录认证中间件
# (没有登录就可以访问: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('用户或密码错误')
获取前端各编码提交数据存储到request.data
无论前端是什么编码的请求,后端视图函数都有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编码
除了method为post其他和get相同
post提交 form-data编码 #包含文件
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
<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>
中间件代码
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]
实现频率限制的功能(同一个ip地址,一分钟只能访问5次)
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
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/282575.html