Django CSRF cookie未正确设置

时间:2022-04-28 07:49:11

Update 7-18:

更新7-18:

Here is my nginx config for the proxy server:

这是我的代理服务器的nginx配置:

server {
    listen 80;
    server_name blah.com; # the blah is intentional

    access_log /home/cheng/logs/access.log;     
    error_log /home/cheng/logs/error.log;       

    location / {
        proxy_pass http://127.0.0.1:8001;         
    }

    location /static {
        alias /home/cheng/diandi/staticfiles;  
    }

    location /images {
        alias /home/cheng/diandi/images;
    }

    client_max_body_size 10M;
}

Here is nginx.conf:

这是nginx.conf:

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip_disable "msie6";

        # Enable Gzip compressed.
        gzip on;

        # Enable compression both for HTTP/1.0 and HTTP/1.1.
        gzip_http_version  1.1;

        # Compression level (1-9).
        # 5 is a perfect compromise between size and cpu usage, offering about
        # 75% reduction for most ascii files (almost identical to level 9).
        gzip_comp_level    5;

        # Don't compress anything that's already small and unlikely to shrink much
        # if at all (the default is 20 bytes, which is bad as that usually leads to
        # larger files after gzipping).
        gzip_min_length    256;

        # Compress data even for clients that are connecting to us via proxies,
        # identified by the "Via" header (required for CloudFront).
        gzip_proxied       any;

        # Tell proxies to cache both the gzipped and regular version of a resource
        # whenever the client's Accept-Encoding capabilities header varies;
        # Avoids the issue where a non-gzip capable client (which is extremely rare
        # today) would display gibberish if their proxy gave them the gzipped version.
        gzip_vary          on;

        # Compress all output labeled with one of the following MIME-types.
        gzip_types
                application/atom+xml
                application/javascript
                application/json
                application/rss+xml
                application/vnd.ms-fontobject
                application/x-font-ttf
                application/x-web-app-manifest+json
                application/xhtml+xml
                application/xml
                application/x-javascript
                font/opentype
                image/svg+xml
                image/x-icon
                text/css
                text/plain
                text/javascript
                text/js
                text/x-component;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

Update 7-15:

更新7-15:

When copying code to the linux machines, I simply replaced the original source code file but didn't delete the old .pyc files which I don't think will cause trouble right?

将代码复制到linux机器时,我只是更换了原始的源代码文件,但没有删除旧的.pyc文件,我认为这些文件不会造成麻烦吗?


Here is the view code:

这是视图代码:

from django.contrib.auth import authenticate, login
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.shortcuts import render

def login_view(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        next_url = request.POST['next']
        if user is not None:
            if user.is_active:
                login(request, user)
                if next_url:
                    return HttpResponseRedirect(next_url)
                return HttpResponseRedirect(reverse('diandi:list'))
        else:
            form = {'errors': True}
            return render(request, 'registration/login.html', {'form': form})

    else:
        form = {'errors': False}
        return render(request, 'registration/login.html', {'form': form})

I got one of those CSRF cookie not set error from Django, but this is not because I forgot to include the {% csrf_token %} in my template.

我从Django得到了其中一个CSRF cookie没有设置错误,但这不是因为我忘了在我的模板中包含{%csrf_token%}。

Here is what I observed:

这是我观察到的:

Access login page #1 try

Inside the Request Header, the cookie value is:

在Request Header中,cookie值为:

csrftoken=yNG8ZmSI4tr2xTLoE9bys8JbSuu9SD34;

In the template:

在模板中:

<input type="hidden" name="csrfmiddlewaretoken" value="9CVlFSxOo0xiYykIxRmvbWyN5iEUHnPB">

In a cookie plugin that I installed on chrome, the actual csrf cookie value is set to:

在我安装在chrome上的cookie插件中,实际的csrf cookie值设置为:

9CVlFSxOo0xiYykIxRmvbWyN5iEUHnPB

Access login page #2 try:

Inside the Request Header, the cookie value is:

在Request Header中,cookie值为:

csrftoken=9CVlFSxOo0xiYykIxRmvbWyN5iEUHnPB;

In the template:

在模板中:

<input type="hidden" name="csrfmiddlewaretoken" value="Y534sU40S8iTubSVGjjh9KQl0FXesVsC">

In a cookie plugin that I installed on chrome, the actual csrf cookie value is set to:

在我安装在chrome上的cookie插件中,实际的csrf cookie值设置为:

Y534sU40S8iTubSVGjjh9KQl0FXesVsC

The pattern

As you can see from the examples above, the cookie value inside the Request Header differs from the actual csrfmiddlewaretoken in the form and the actual cookie value being set.

从上面的示例中可以看出,Request Header中的cookie值与表单中的实际csrfmiddlewaretoken和设置的实际cookie值不同。

The cookie value of the current request matches the next request header's cookie value.

当前请求的cookie值与下一个请求标头的cookie值匹配。


To help debugging, here is a portion of my `settings.py:

为了帮助调试,这是我的`settings.py的一部分:

DJANGO_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

THIRD_PARTY_APPS = (
    'compressor',
    'crispy_forms',
    'django_extensions',
    'floppyforms',
    'multiselectfield',
    'admin_highcharts',
)

LOCAL_APPS = (
    'diandi_project',
    'uer_application',
)

INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

MIDDLEWARE_CLASSES = (
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [str(ROOT_DIR.path('templates'))],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.media',
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

I am using Django 1.9.5 and python 2.7.10.

我正在使用Django 1.9.5和python 2.7.10。

One "solution"

I have encountered this problem before, I can clear all my browser cookies and the site will function properly. But this problem will eventually come up again, so I am really hoping someone can help me out (I probably just made a really dumb mistake somewhere).

我以前遇到过这个问题,我可以清除所有浏览器cookie,网站也能正常运行。但这个问题最终会再次出现,所以我真的希望有人可以帮助我(我可能只是在某个地方犯了一个非常愚蠢的错误)。

Update

Originally, I thought I made some mistakes while overriding the django.contrib.auth.view page, so I wrote my own login page handler and it still causes the issue.

最初,我认为在覆盖django.contrib.auth.view页面时犯了一些错误,所以我编写了自己的登录页面处理程序,但仍然会导致问题。

Here is the core part of my login template:

这是我的登录模板的核心部分:

{% block content %}
...

                <form method="post" action="{% url 'login' %}">
                    {% csrf_token %}

                    <div class="form-group">
                        <label for="username">username</label>
                        <input type="text" class="form-control" id="id_username" name="username">
                    </div>
                    <div class="form-group">
                        <label for="password">password</label>
                        <input type="password" class="form-control" id="id_password" name="password">
                    </div>

                    <input type="submit" class="btn btn-default" value="login" />
                    <input type="hidden" id="next" name="next" value="" />
                </form>

...

{% endblock %}

On the Linux machines, I have a nginx server setup as a reverse proxy which direct request on port 80 to 8001, and I am running the server using ./manage runserver localhost:8001 This is the only difference I can think of in terms of setup. Otherwise, all of the source code and settings file are identical.

在Linux机器上,我有一个nginx服务器设置作为反向代理,它将端口80上的请求定向到8001,我使用./manage runserver localhost:8001运行服务器这是我能想到的唯一区别建立。否则,所有源代码和设置文件都是相同的。


I started deleting cookies but not all of them, this is what I see before deleting them:

我开始删除cookie但不是全部删除,这是我在删除它之前看到的:

Django CSRF cookie未正确设置

I deleted all the cookies other than djdt and csrftoken, then the page worked. Could the deleted cookies somehow go over some limit which prevent the csrftoken which is further down the list from being set?

我删除了除djdt和csrftoken之外的所有cookie,然后页面工作了。被删除的cookie是否会以某种方式超过一些限制,以防止列表中的csrftoken被设置?

Here is the cookie value of the image above in the request header:

以下是请求标头中上图中的cookie值:

Cookie:PSTM=1466561622; BIDUPSID=6D0DDB8084625F2CEB7B9D0F14F93391; BAIDUID=326150BF5A6DFC69B6CFEBD67CA7A18B:FG=1; BDSFRCVID=Fm8sJeC62leqR8bRqWS1u8KOKg9JUZOTH6ao6BQjXAcTew_mbPF_EG0PJOlQpYD-hEb5ogKK0mOTHvbP; H_BDCLCKID_SF=tJPqoCtKtCvbfP0k-tcH244HqxbXq-r8fT7Z0lOnMp05EnnjKl5M3qKOqJraJJ585Gbb5tOhaKj-VDO_e6u-e55LjaRh2PcM2TPXQ458K4__Hn7zep0aqJtpbt-qJjbOfmQBbfoDQCTDfho5b63JyTLqLq5nBT5Ka26WVpQEQM5c8hje-4bMXPkkQN3T-TJQL6RkKTCyyx3cDn3oyToVXp0njGoTqj-eJbA8_CtQbPoHHnvNKCTV-JDthlbLetJyaR3lWCnbWJ5TMCo1bJQCe-DwKJJgJRLOW2Oi0KTFQxccShPC-tP-Ll_qW-Q2LPQfXKjabpQ73l02VhcOhhQ2Wf3DM-oat4RMW20jWl7mWPQDVKcnK4-Xj533DHjP; BDUSS=5TNmRvZnh2eUFXZDA5WXI5UG1HaXYwbzItaWt3SW5adjE1Nn5XbUVoWHZuYXBYQVFBQUFBJCQAAAAAAAAAAAEAAAC0JtydAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO8Qg1fvEINXSU; Hm_lvt_a7708f393bfa27123a1551fef4551f7a=1468229606; Hm_lpvt_a7708f393bfa27123a1551fef4551f7a=1468229739; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; cflag=15%3A3; H_PS_PSSID=1424_20515_13289_20536_20416_19861_14994_11792; csrftoken=xUgSHybzHeIwusN0GvMgB1ATeRrPgcV1

Since the site functions now, all I have are five cookies instead of 14 like the image above:

由于网站现在运行,我只有五个饼干,而不是像上图中的14个:

Django CSRF cookie未正确设置

1 个解决方案

#1


17  

Here is the issue: You cannot have a cookie which key contains either the character '[' or ']'

问题在于:您不能拥有一个cookie,其中哪个键包含字符'['或']'

I discovered the solution following @Todor's link, then I found out about this SO post. Basically there was a bug in python 2.7.x that does not parse cookies with ']' in the value. The bug was fixed in 2.7.10.

我在@Todor链接后发现了解决方案,然后我发现了这个SO帖子。基本上python 2.7.x中有一个错误,它不会在值中解析带有']'的cookie。该错误已在2.7.10中修复。

I thought it would be good to just confirm this issue. So I dug through all of the cookies and found one with the following key/value:

我认为只是确认这个问题会很好。所以我挖掘了所有的cookie并找到了一个具有以下键/值的cookie:

key: BDRCVFR[feWj1Vr5u3D]
val: I67x6TjHwwYf0

So I inserted the following cookie locally and submitted to the server:

所以我在本地插入了以下cookie并提交给服务器:

key: test
val: BDRCVFR[feWj1Vr5u3D]

The login page worked, which means 2.7.10 indeed fixed the bug.

登录页面工作,这意味着2.7.10确实修复了错误。

But then I realized that the square brackets are actually in the key name not in the value, so I did the following tests:

但后来我意识到方括号实际上是键值而不是值,所以我做了以下测试:

key: [
val: I67x6TjHwwYf0

and

key:]
val: I67x6TjHwwYf0

Both cookies break the login process and django displays:

这两个cookie都会破坏登录过程并显示django:

CSRF cookie not set

So either django or a python library it relies on cannot parse cookies with square brackets in names properly. If anybody knows where I should submit this bug please let me know (django or python).

因此,它所依赖的django或python库无法正确解析名称中带方括号的cookie。如果有人知道我应该在哪里提交此bug,请告诉我(django或python)。

I would like to thank everybody who left a comment in the OP: @raphv, @trinchet, @Phillip, @YPCrumble, @PeterBrittain and @Todor. Thank you guys so much for debugging with me!

我要感谢所有在OP中发表评论的人:@raphv,@ trinchet,@ Phipip,@ YPCrumble,@ PeterBrittain和@Todor。非常感谢你们和我一起调试!


Update: July 20, 2016

This bug is fixed in Django 1.10, just have to wait for the release

这个错误在Django 1.10中修复,只需要等待发布

Update: July 19, 2016

I filed a bug report to Django as the result of this post. We will see if it will be fixed in future releases.

作为这篇文章的结果,我向Django提交了一份错误报告。我们将看看它是否会在将来的版本中修复。

#1


17  

Here is the issue: You cannot have a cookie which key contains either the character '[' or ']'

问题在于:您不能拥有一个cookie,其中哪个键包含字符'['或']'

I discovered the solution following @Todor's link, then I found out about this SO post. Basically there was a bug in python 2.7.x that does not parse cookies with ']' in the value. The bug was fixed in 2.7.10.

我在@Todor链接后发现了解决方案,然后我发现了这个SO帖子。基本上python 2.7.x中有一个错误,它不会在值中解析带有']'的cookie。该错误已在2.7.10中修复。

I thought it would be good to just confirm this issue. So I dug through all of the cookies and found one with the following key/value:

我认为只是确认这个问题会很好。所以我挖掘了所有的cookie并找到了一个具有以下键/值的cookie:

key: BDRCVFR[feWj1Vr5u3D]
val: I67x6TjHwwYf0

So I inserted the following cookie locally and submitted to the server:

所以我在本地插入了以下cookie并提交给服务器:

key: test
val: BDRCVFR[feWj1Vr5u3D]

The login page worked, which means 2.7.10 indeed fixed the bug.

登录页面工作,这意味着2.7.10确实修复了错误。

But then I realized that the square brackets are actually in the key name not in the value, so I did the following tests:

但后来我意识到方括号实际上是键值而不是值,所以我做了以下测试:

key: [
val: I67x6TjHwwYf0

and

key:]
val: I67x6TjHwwYf0

Both cookies break the login process and django displays:

这两个cookie都会破坏登录过程并显示django:

CSRF cookie not set

So either django or a python library it relies on cannot parse cookies with square brackets in names properly. If anybody knows where I should submit this bug please let me know (django or python).

因此,它所依赖的django或python库无法正确解析名称中带方括号的cookie。如果有人知道我应该在哪里提交此bug,请告诉我(django或python)。

I would like to thank everybody who left a comment in the OP: @raphv, @trinchet, @Phillip, @YPCrumble, @PeterBrittain and @Todor. Thank you guys so much for debugging with me!

我要感谢所有在OP中发表评论的人:@raphv,@ trinchet,@ Phipip,@ YPCrumble,@ PeterBrittain和@Todor。非常感谢你们和我一起调试!


Update: July 20, 2016

This bug is fixed in Django 1.10, just have to wait for the release

这个错误在Django 1.10中修复,只需要等待发布

Update: July 19, 2016

I filed a bug report to Django as the result of this post. We will see if it will be fixed in future releases.

作为这篇文章的结果,我向Django提交了一份错误报告。我们将看看它是否会在将来的版本中修复。