Django 设置 cookie 中的 csrftoken

Posted Wang-Vee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 its 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

以上是关于Django 设置 cookie 中的 csrftoken的主要内容,如果未能解决你的问题,请参考以下文章

Django 设置 cookie 中的 csrftoken

Django 中的 Cookie 和 Session

CSRF错误Django ajax .post没有表格

Django中的cookie和session

Django中的路径特定Cookie

Django中的会话技术(Cookie,Session,Token)