未设置Django CSRF Coo​​kie


85

我有一阵子的问题,我没有设置CSRF Coo​​kie。请看下面的代码

蟒蛇

def deposit(request,account_num):
if request.method == 'POST':
    account = get_object_or_404(account_info,acct_number=account_num)
    form_=AccountForm(request.POST or None, instance=account)
    form = BalanceForm(request.POST)
    info = str(account_info.objects.filter(acct_number=account_num))
    inf=info.split()
    if form.is_valid():
    #cd=form.cleaned_data
        now = datetime.datetime.now()
        cmodel = form.save()
        cmodel.acct_number=account_num
        #RepresentsInt(cmodel.acct_number)
        cmodel.bal_change="%0.2f" % float(cmodel.bal_change)
        cmodel.total_balance="%0.2f" %(float(inf[1]) + float(cmodel.bal_change))
        account.balance="%0.2f" % float(cmodel.total_balance)
        cmodel.total_balance="%0.2f" % float(cmodel.total_balance)
        #cmodel.bal_change=cmodel.bal_change
        cmodel.issued=now.strftime("%m/%d/%y %I:%M:%S %p")
        account.recent_change=cmodel.issued
        cmodel.save()
        account.save()
        return HttpResponseRedirect("/history/" + account_num + "/")
    else:
        return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))

在HTML中,这是代码

的HTML

<form action="/deposit/{{ account_num }}/" method="post">

<table>
<tr>
{{ account_form.bal_change }}
&nbsp;
<input type="submit" value="Deposit" />
</tr>
{% csrf_token %}
</table>
</form>

我卡住了,我已经清除了cookie,使用了其他浏览器,但仍然没有设置csrf cookie。


你有CsrfViewMiddleware你的MIDDLEWARE_CLASSES环境吗?
alecxe

{%csrf_token%}在模板中添加表格。
罗汉

4
@Rohan已经存在了,请参阅问题。
alecxe

1
是的,我已经有CsrfViewMiddleware,并且我的表单中已经有csrf_token

我一直在使用Django cors模块,并通过ReactJS访问它。(都在本地主机上)。我也遇到了OP的问题。我发现我添加credentials: 'include'到POST请求中,然后还添加了django的settings.py:CORS_ALLOW_CREDENTIALS = True似乎已经解决了该问题,而无需添加@csrf_exempt到视图中。它实际上是在文档... pypi.org/project/django-cors-headers-multi *我知道这涉及到的上述问题之一,但我还不能发表评论,并希望希望保存别人的时间就带我找到t
DW

Answers:


133

如果CSRF_COOKIE_SECURE = True设置了并且您非安全地访问该站点,或者CSRF_COOKIE_HTTPONLY = True按照此处此处所述进行设置,也会发生这种情况


10
谢谢!同样适用SESSION_COOKIE_SECURE = True
NonameSL '18年

75
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt 
def your_view(request):
    if request.method == "POST":
        # do something
    return HttpResponse("Your response")

59
完全禁用安全机制不是修复错误的好方法。
纪尧姆·阿尔吉斯

2
如果您在2017年使用cookiecutter-django,这是生产中的正确答案。
安德烈·杜阿尔特

1
为什么出于好奇?
Patrick Gallagher

3
该答案并不建议“完全禁用安全性机制”,它仅告诉您在可能无法使用CSRF令牌的单个情况下如何执行此操作。这是我的情况,我需要向外部客户端提供POST操作。
mariotomo19年

当您无法从UI提供csrf令牌时,这是我在开发阶段使用的TODO物品。但肯定不建议用于实时应用程序。
阿曼·马丹

24

如果您使用HTML5 Fetch API作为登录用户并发出POST请求Forbidden (CSRF cookie not set.),则可能是因为默认情况下fetch不包含会话Cookie,导致Django认为您与加载页面的用户不同。 。

您可以通过传递以下选项credentials: 'include'来包含会话令牌:

var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
    method: 'POST',
    body: payload,
    headers: headers,
    credentials: 'include'
})

我可以知道您实例化的Header()方法是什么吗?这是全局javascript方法吗?
Abz Rockers

@AbzRockers:是的,Headers是全局javascript接口,是HTML5 Fetch API的一部分。developer.mozilla.org/en-US/docs/Web/API/Headers
user85461 '18年

13

通过此操作, 您可以通过在您的视图中添加sure_csrf_cookie装饰器来解决它

from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def yourView(request):
 #...

如果此方法不起作用。您将尝试在中间件中注释csrf。然后再次测试。


5

我在使用DRF时遇到了类似的情况,该解决方案是将.as_view()方法附加到urls.py中的View上。


如果您还包括一些代码,那就更好了
Alex Jolig

1
@AlexJolig刚刚遇到了同样的问题,问题是我忘了在.as_view()ApiView后面添加代码,所以代码看起来像这样: urlpatterns += path('resource', ResourceView)那就应该这样:urlpatterns += path('resource', ResourceView.as_view())
Alveona

4

如果您使用的是DRF,请检查urlpatterns是否正确,也许您忘记了.as_view()

这样我的代码看起来像这样:

urlpatterns += path('resource', ResourceView) 

这就是它的样子:

urlpatterns += path('resource', ResourceView.as_view())

1

尝试检查您是否已在settings.py中安装

 MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',)

在模板中,数据使用csrf_token格式化:

<form>{% csrf_token %}
</form>

我没有您的所有代码,但我认为这是在这里:def deposit(request,account_num):将其更改为def deposit(request):并找到一种回调account_num的方法。现在将取决于account_num是表字段还是变量。
drabo2005

它是一个变量{{account_num}},但这如何影响csrf令牌?

我相信csrf令牌仅引用了request,因此它无法在此处验证或处理变量的处理方式。检查djangoproject.com可能是您可以获得有关csrf_token的正确答案。
drabo2005


1

当您未设置表单操作时,也会发生这种情况。
对我来说,当代码为:

<form class="navbar-form form-inline my-2 my-lg-0" role="search" method="post">

当我将代码更正为:

<form class="navbar-form form-inline my-2 my-lg-0" action="{% url 'someurl' %}" role="search" method="post">

我的错误消失了。


0

问题似乎是您没有GET适当地处理请求,或者没有先获取表格就直接发布数据。

首次访问该页面时,客户端将发送GET请求,在这种情况下,您应该以适当的形式发送html。

稍后,用户填写表格并发送 POST带有表单数据的请求。

您的观点应该是:

def deposit(request,account_num):
   if request.method == 'POST':
      form_=AccountForm(request.POST or None, instance=account)
      if form.is_valid(): 
          #handle form data
          return HttpResponseRedirect("/history/" + account_num + "/")
      else:
         #handle when form not valid
    else:
       #handle when request is GET (or not POST)
       form_=AccountForm(instance=account)

    return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))

0

检查chrome的cookie是否已设置为网站的默认选项。允许设置本地数据(推荐)。


0

方法1:

from django.shortcuts import render_to_response
return render_to_response(
    'history.html',
    RequestContext(request, {
        'account_form': form,
    })

方法2:

from django.shortcuts import render
return render(request, 'history.html', {
    'account_form': form,
})

因为render_to_response方法可能会遇到一些响应cookie问题。


0

我刚刚见过一次,解决方法是清空Cookie。并且可能在调试与SECRET_KEY相关的时候更改。


0

清除浏览器的缓存可以为我解决此问题。在发生另一个项目之后,我一直在本地开发环境之间切换,以执行django-blog-zinnia教程。起初,我以为更改INSTALLED_APPS的顺序以使其与本教程相匹配就导致了这种情况,但是我将其重新设置了,直到清除缓存后才能够对其进行更正。


0

我以前使用的是Django 1.10,所以我遇到了这个问题。现在,我将其降级为Django 1.9,并且工作正常。


使用1.10.3我有这个问题。升级到1.10.6为我修复了它。
Mike Darmetko

0

我有同样的错误,在我的情况下添加method_decorator可以帮助:

from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator

method_decorator(csrf_protect)
def post(self, request):
    ...

0

确保在settings.py中正确配置了django会话后端。然后试试这个

class CustomMiddleware(object):
  def process_request(self,request:HttpRequest):
      get_token(request)

settings.pyMIDDLEWARE_CLASSES或下添加此中间件MIDDLEWARE在django版本根据django版本

get_token-返回POST表单所需的CSRF令牌。令牌是字母数字值。如果尚未设置新令牌,则会创建一个新令牌。


-4

在您看来,您正在使用csrf装饰器吗?

from django.views.decorators.csrf import csrf_protect

@csrf_protect def view(request, params): ....

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.