Django 設置 cookie 中的 csrftoken


遇到一個問題是,CMDB項目的前端刪除數據要向后端發送 DELETE 請求,需要驗證 CSRF 。但是之前項目一直都是 GET 請求獲取的數據,瀏覽器的 cookies 中沒有 csrftoken 的值,而發送請求之前是從 cookies 中獲取 csrftoken 的值,沒有值也就沒法通過驗證。所以就要人為的設置一下 cookies 中的 csrftoken 值。

  出現這個問題的前提是:

  1、習慣ajax方式提交POST等請求;

  2、習慣從cookie中找csrftoken;

  一般我們認為cookie里的csrftoken是由csrftoken middleware所設置的,事實確實如此,但也不完全是。貼一段CsrfViewMiddleware的代碼:

def process_response(self, request, response):
        if not getattr(request, 'csrf_cookie_needs_reset', False):
            if getattr(response, 'csrf_cookie_set', False):
                return response

        if not request.META.get("CSRF_COOKIE_USED", False):
            return response

        # Set the CSRF cookie even if it's already set, so we renew
        # the expiry timer.
        self._set_token(request, response)
        response.csrf_cookie_set = True
        return response
def _set_token(self, request, response):
        if settings.CSRF_USE_SESSIONS:
            request.session[CSRF_SESSION_KEY] = request.META['CSRF_COOKIE']
        else:
            response.set_cookie(
                settings.CSRF_COOKIE_NAME,
                request.META['CSRF_COOKIE'],
                max_age=settings.CSRF_COOKIE_AGE,
                domain=settings.CSRF_COOKIE_DOMAIN,
                path=settings.CSRF_COOKIE_PATH,
                secure=settings.CSRF_COOKIE_SECURE,
                httponly=settings.CSRF_COOKIE_HTTPONLY,
            )
            # Set the Vary header since content varies with the CSRF cookie.
            patch_vary_headers(response, ('Cookie',))

這段代碼的重點在於對CSRF_COOKIE_USED的檢查,如果沒有設置,middleware會直接返回response而不在cookie里設置csrftoken。

看別人說有三種方法設置CSRF_COOKIE_USED。

1. 手動設置,在view 中添加 

request.META["CSRF_COOKIE_USED"] = True

2. 手動調用 csrf 中的 get_token(request) 或 rotate_token(request) 方法。

from django.middleware.csrf import get_token ,rotate_token

def server(request):

    # get_token(request)       // 兩者選一
    # rotate_token(request)   // 此方法每次設置新的cookies

    return render(request, 'server.html')

3. 在HTML模板中添加 {% csrf_token %}

4. 在需要設置cookie的視圖上加裝飾器 ensure_csrf_cookie()

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def server(request):

    return render(request, 'server.html')

親測方法2、3、4有效,都能在cookie中設置csrftoken,但是方法1會報錯,需要自己生成64位的csrftoken。

request.META['CSRF_COOKIE']= 'abc' 配合此行代碼,cookie中的csrftoken設置成了‘abc’.

所以,如果不想在模板中添加{% csrf_token %}標簽,推薦使用方法2中的get_token(request)方法和方法4

CSRF保護機制的工作原理:https://docs.djangoproject.com/en/1.11/ref/csrf/#how-it-works

參考:http://www.jianshu.com/p/9346bbc3a8f1


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM