ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Django入门到放弃之CSRF_TOKEN

2022-08-27 23:30:34  阅读:133  来源: 互联网

标签:CSRF get request Django TOKEN csrf password data name


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

  

标签:CSRF,get,request,Django,TOKEN,csrf,password,data,name
来源: https://www.cnblogs.com/panwenbin-logs/p/16631792.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有