파이썬 개발자 [장고] : 미들웨어, CSRF

파이썬 개발자 [장고] : 미들웨어, CSRF

CSRF

1. 개요

  사용자가 사이트에 로그온 할 경우 CSRF (크로스 사이트 요청 위조) 크로스 사이트 요청 위조는 측면에서, 예를 들어, 귀하의 사이트에 대한 링크가, 다음 사용자가 악의적 인 웹 사이트를 클릭 할 때 악의적 인 웹 사이트에 대한 링크가, 요청이 사이트로 전송됩니다 때, 귀하의 사이트는이 요청을 사용자 고유의, 실제로,이 요청은 그 악의적 인 가짜 웹 사이트로 전송하고 있다고 생각합니다.

  위의 상황을 피하려면, 장고 CSRF 보호 메커니즘을 인용, 클라이언트의 요청에 대한 첫 번째 응답, 그것은 무작위로 서버 측에서 토큰을 생성하고, 쿠키에 토큰을 넣어 것 장고 때. POST 요청되는 CSRF 공격을 피하기 위해 각 시간이 토큰을 가져올 것입니다. 더 POST 요청 토큰 임의의 문자열이없는 경우, 서비스 (403)의 거부를 반환

  • 쿠키 HTTP 응답이 내부 반환에서, 장고는 값이 자동으로 토큰에 의해 생성되는, 당신을 위해 csrftoken 필드를 추가합니다
  • POST가 양식을 모두하는 csrfmiddlewaretoken 필드를 포함해야합니다 때 (리가 하나 개의 템플릿 태그, 장고가 자동으로 아래 참조, 생성하는 데 도움이됩니다)
  • 값과 POST 요구가 처리되기 전에 csrfmiddlewaretoken 필드의 형태로 제출은 장고 동일 여부 csrftoken 분야에서 과자의 요청을 확인한다. 그것은이 그렇지 않으면, 합법적 인 요청을 나타냅니다으로, 요청이 다른 사람의 CSRF 공격에서 올 수있는 경우, 고궁 (403)를 반환합니다.
  • X-CSRFTOKEN 헤더 값이 쿠키의 값을 모두 추가 AJAX POST 요청에 csrftoken되고

이제 우리는 settings.py에서 미들웨어 django.middleware.csrf.CsrfViewMiddleware를 활성화해야합니다 :

`MIDDLEWARE ``=` `[``    ``'django.middleware.csrf.CsrfViewMiddleware'``,``]`

지역 사용하기 :

  • @csrf_protect, 설정이 전체 미들웨어를 설정되지 않은 경우에도, 현재 함수 CSRF 방지 기능에 강요했다.
  • @csrf_exempt, 글로벌 설정이 미들웨어에 설정 한 경우에도, 현재 함수의 CSRF 방지 기능을 취소합니다.

사용 CBA :

`from` `django.utils.decorators ``import` `method_decorator``class` `AssetView(View):``    ``@method_decorator``(csrf_exempt)     ``#必须加到dispatch上,get、post上都不好使``    ``def` `dispatch(``self``, request, ``*``args, ``*``*``kwargs):``        ``return` `super``(AssetView, ``self``).dispatch(request, ``*``args, ``*``*``kwargs)`

  

(2) 폼 POST 요청 양식 제출

파일 :

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'root' and pwd == "123":
            # 生成随机字符串
            # 写到用户浏览器Cookie
            # 保存到Session中
            # 在随机字符串对应的字典中设置相关内容...
            request.session['username'] = user
            request.session['if_login'] = True  #可不加 直接判断username也可以
            if request.POST.get('session') == '1':    #单独设置超时时间,当前session生效,不影响全局
                request.session.set_expiry(10)      #10秒
            return redirect('/index/')
        else:
            return redirect('/login/')

def index(request):
    # 获取当前用户的随机字符串
    # 根据随机字符串获取对应信息
    if request.session.get('if_login'):
        return render(request, 'index.html')
    else:
        return redirect('/login/')

login.html 파일 :

`{``# 添加{% csrf_token %} #}``<!DOCTYPE html>``<html lang``=``"en"``>``<head>``    ``<meta charset``=``"UTF-8"``>``    ``<title>Title<``/``title>``<``/``head>``<body>``    ``<form action``=``"/login/"` `method``=``"post"``>``        ``{``%` `csrf_token ``%``}``        ``<``input` `type``=``"text"` `name``=``"user"` `/``>``        ``<``input` `type``=``"text"` `name``=``"pwd"` `/``>``        ``<``input` `type``=``"checkbox"` `name``=``"session"` `value``=``"1"``/``> 保存``1``个月``        ``<``input` `type``=``"submit"` `value``=``"提交"` `/``>``    ``<``/``form>``<``/``body>``<``/``html>`

3, 아약스는 POST 요청을 제출

파일 :

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'root' and pwd == "123":
            # 生成随机字符串
            # 写到用户浏览器Cookie
            # 保存到Session中
            # 在随机字符串对应的字典中设置相关内容...
            request.session['username'] = user
            request.session['if_login'] = True  #可不加 直接判断username也可以
            if request.POST.get('session') == '1':    #单独设置超时时间,当前session生效,不影响全局
                request.session.set_expiry(10)      #10秒
            return redirect('/index/')
        else:
            return redirect('/login/')

def index(request):
    # 获取当前用户的随机字符串
    # 根据随机字符串获取对应信息
    if request.session.get('if_login'):
        return render(request, 'index.html')
    else:
        return redirect('/login/')

login.html 파일 :

`{``# Ajax提交时要添加headers值 #}``<!DOCTYPE html>``<html lang``=``"en"``>``<head>``    ``<meta charset``=``"UTF-8"``>``    ``<title>Title<``/``title>``<``/``head>``<body>``    ``<form action``=``"/login/"` `method``=``"post"``>``        ``{``%` `csrf_token ``%``}               ``        ``<``input` `type``=``"text"` `name``=``"user"` `/``>``        ``<``input` `type``=``"text"` `name``=``"pwd"` `/``>``        ``<``input` `type``=``"checkbox"` `name``=``"session"` `value``=``"1"``/``> 保存``1``个月``        ``<``input` `id``=``'btn'` `type``=``"button"` `value``=``"Ajax提交"` `/``>``    ``<``/``form>``    ``<script src``=``"/static/jquery-1.12.4.js"``><``/``script>``    ``<script src``=``"/static/jquery.cookie.js"``><``/``script>``    ``<script>``        ``$(function () {``            ``$(``'#btn'``).click(function () {``                ``$.ajax({``                    ``url:``'/login/'``,``                    ``type``:``'POST'``,``                    ``data:{``'user'``:``'root'``,``'pwd'``:``'123'``},``                    ``headers:{``'X-CSRFtoken'``:$.cookie(``'csrftoken'``)},``                    ``success:function (arg) {``                    ``}``                ``})``            ``})``        ``})``    ``<``/``script>``<``/``body>``<``/``html>`

위의 HTML 파일 후, 제출 성공적인 실행을 클릭합니다,하지만 종종 프로그램은 Ajax 요청보다 더 많은, 그래서 우리 모두는 각 요청에 대해 헤더 Ajax 요청 헤더를 추가해야 할 일이 너무 너무 엄청난 양의 다음, 당신은 모든이없는, 전역 설정을 할 필요가 요청 헤더 추가

{# Ajax提交时全局生效 #}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/login/" method="post">
        {% csrf_token %}
        <input type="text" name="user" />
        <input type="text" name="pwd" />
        <input type="checkbox" name="session" value="1"/> 保存1个月
        <input id='btn' type="button" value="Ajax提交" />
    </form>
    <script src="/static/jquery-1.12.4.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        $(function () {
{#            全局配置,所有Ajax请求都先执行下面操作#}
            $.ajaxSetup({
                beforeSend:function (xhr,settings) {
                    xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
                }
            });

            $('#btn').click(function () {
                $.ajax({
                    url:'/login/',
                    type:'POST',
                    data:{'user':'root','pwd':'123'},
                    success:function (arg) {

                    }
                })
            })
        })
    </script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    {% csrf_token %}
  
    <input type="button" onclick="Do();"  value="Do it"/>
  
    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
    <script src="/static/plugin/jquery/jquery.cookie.js"></script>
    <script type="text/javascript">
        var csrftoken = $.cookie('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);
                }
            }
        });
        function Do(){
  
            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });
  
        }
    </script>
</body>
</html>

미들웨어

1. 개요

  장고 미들웨어 (미들웨어)에서는, 장고 미들웨어 실제로 클래스이고, 상기 요청의 도착 후에있어서 해당 장고 미들웨어는 자신의 규칙에 따라 적절한 시간에 실행된다; 장고 프로젝트 설정 다음 모듈의 각 요소가 중간이고 변수 미들웨어이다 :

`MIDDLEWARE ``=` `[``    ``'django.middleware.security.SecurityMiddleware'``,``    ``'django.contrib.sessions.middleware.SessionMiddleware'``,``    ``'django.middleware.common.CommonMiddleware'``,``    ``'django.middleware.csrf.CsrfViewMiddleware'``,``    ``'django.contrib.auth.middleware.AuthenticationMiddleware'``,``    ``'django.contrib.messages.middleware.MessageMiddleware'``,``    ``'django.middleware.clickjacking.XFrameOptionsMiddleware'``,``]`

네 가지 방법을 정의 할 수 있습니다 미들웨어는 다음과 같습니다

  • process_request 스킵을 수행하는 다음의 중간 기록되지 실행 요청 (자기 요청), 리턴 HttpResonse,하기 중간체가 실행되지 않을 때
  • process_view (자기, 요청 콜백 callback_args, callback_kwargs) 개시 후 process_request 제 구현, 실행부터 다시 시작 proces_view
  • 객체가 렌더링 메소드를 갖는 함수 뷰에 반환되는 경우 process_template_response (자기, 요청 응답),이 방법을 수행
  • process_exception 기능 실행 오류 views.py은이 방법이 수행된다 (자동 요청 예외) 이상 수행 트리거; 에러는 최고 우선 순위 예외의 최저 레벨, 최근의 실행 및 실행 방법 respnse 발생시
  • process_response (자기, 요청 응답) 스킵을 수행하는 다음의 중간 기록되지 실행 요구를 반환 복귀 HttpResonse는, 원래의 데이터와 교체

그 중에없는 경우, 상기 방법의 반환 값 없음 HttpResonse 객체는 객체가 사용자에게 직접 반환되는 경우 다음의 규칙에 따라 정의 장고 속행, HttpResonse 개체 없을 수 있고

IMG

참고 : 장고 버전 1.10 이후 직접 실행 process_response 동일한 수준의 대신 가장 낮은 process_response에서 시작

2, 사용자 정의 미들웨어

장고의 홈 디렉토리 아래에 디렉토리 미들웨어 (모든 이름) 만들기 디렉토리 m.py에서 파일을 생성

① process_request, process_response

파일의 사용자 정의 미들웨어 클래스 :

`from` `django.utils.deprecation ``import` `MiddlewareMixin``from` `django.shortcuts ``import` `HttpResponse` `class` `Row1(MiddlewareMixin):``    ``def` `process_request(``self``,request):``        ``print``(``"王森1"``)``        ``# return HttpResponse("DDDD")``    ``def` `process_response(``self``,request,response):``        ``print``(``"扛把子1"``)``        ``return` `response` `class` `Row2(MiddlewareMixin):``    ``def` `process_request(``self``,request):``        ``print``(``"王森2"``)``    ``def` `process_response(``self``, request, response):``        ``print``(``"扛把子3"``)``        ``return` `response` `class` `Row3(MiddlewareMixin):``    ``def` `process_request(``self``,request):``        ``print``(``"王森3"``)``    ``def` `process_response(``self``, request, response):``        ``print``(``"扛把子3"``)``        ``return` `response`

미들웨어 설정 파일을 로그인 :

`from` `django.middleware.csrf ``import`  `CsrfViewMiddleware``MIDDLEWARE ``=` `[``    ``'django.middleware.security.SecurityMiddleware'``,``    ``'django.contrib.sessions.middleware.SessionMiddleware'``,``    ``'django.middleware.common.CommonMiddleware'``,``    ``'django.middleware.csrf.CsrfViewMiddleware'``,``    ``'django.contrib.auth.middleware.AuthenticationMiddleware'``,``    ``'django.contrib.messages.middleware.MessageMiddleware'``,``    ``'django.middleware.clickjacking.XFrameOptionsMiddleware'``,``    ``'middleware.m.Row1'``,``    ``'middleware.m.Row2'``,``    ``'middleware.m.Row3'``,`

인쇄가 수행됩니다 

王森1
王森2
王森3
走你
扛把子3
扛把子3
扛把子1

② process_view

파일의 사용자 정의 미들웨어 클래스 :

`from` `django.utils.deprecation ``import` `MiddlewareMixin``from` `django.shortcuts ``import` `HttpResponse` `class` `Row1(MiddlewareMixin):``    ``def` `process_request(``self``,request):``        ``print``(``"王森1"``)``    ``def` `process_view(``self``, request, view_func, view_func_args, view_func_kwargs):``        ``print``(``"James1"``)``    ``def` `process_response(``self``,request,response):``        ``print``(``"扛把子1"``)``        ``return` `response` `class` `Row2(MiddlewareMixin):``    ``def` `process_request(``self``,request):``        ``print``(``"王森2"``)``    ``def` `process_view(``self``, request, view_func, view_func_args, view_func_kwargs):``        ``print``(``"James2"``)``    ``def` `process_response(``self``, request, response):``        ``print``(``"扛把子3"``)``        ``return` `response` `class` `Row3(MiddlewareMixin):``    ``def` `process_request(``self``,request):``        ``print``(``"王森3"``)``    ``def` `process_view(``self``, request, view_func, view_func_args, view_func_kwargs):``        ``print``(``"James3"``)``    ``def` `process_response(``self``, request, response):``        ``print``(``"扛把子3"``)``        ``return` `response`

인쇄가 수행됩니다

王森1
王森2
王森3
James1
James2
James3
走你
扛把子3
扛把子3
扛把子1

추천

출처www.cnblogs.com/TMesh/p/11735928.html