【问题标题】:Django CSRF Cookie Not SetDjango CSRF Coo​​kie 未设置
【发布时间】:2013-07-16 23:59:50
【问题描述】:

我现在有一些问题,我遇到了 CSRF Coo​​kie not set。请看下面的代码

Python

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

<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。

【问题讨论】:

  • 您的MIDDLEWARE_CLASSES 设置中有CsrfViewMiddleware 吗?
  • 在模板中的表单中添加{%csrf_token%}
  • @Rohan 它已经存在了,请参阅问题。
  • 是的,我已经有了 CsrfViewMiddleware,并且我的表单中已经有了 csrf_token
  • 我一直在使用 Django cors 模块并通过 ReactJS 访问它。 (两者都在本地主机上)。我也有这个OP的问题。我发现在 POST 请求中添加 credentials: 'include',然后在 django 的 settings.py 中添加:CORS_ALLOW_CREDENTIALS = True 似乎已经解决了问题,而无需在视图中添加 @csrf_exempt。它实际上在文档中...pypi.org/project/django-cors-headers-multi *我知道这与上述问题之一有关,但我还不能发表评论,希望能节省其他人我找到 t 所花费的时间

标签: python django


【解决方案1】:

如果设置了 CSRF_COOKIE_SECURE = True 并且您正在不安全地访问该站点,或者如果 CSRF_COOKIE_HTTPONLY = True 设置为 herehere 所述,也会发生这种情况

【讨论】:

  • 谢谢! SESSION_COOKIE_SECURE = True 也是如此。
【解决方案2】:
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")

【讨论】:

  • 完全禁用安全机制并不是修复错误的好方法。
  • 如果您在 2017 年使用 cookiecutter-django,这是生产中的正确答案。
  • 为什么会这样,出于好奇?
  • 此答案并不建议“完全禁用安全机制”,它仅说明如何针对您可能无法使用 CSRF 令牌的单个情况执行此操作。这是我的情况,我需要向外部客户端提供 POST 操作。
  • 这是我在开发阶段使用的一种 TODO 项目,当您无法从 UI 提供 csrf 令牌时。但肯定不推荐用于实时应用。
【解决方案3】:

如果您使用 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'
})

【讨论】:

【解决方案4】:

来自This 您可以通过将ensure_csrf_cookie decorator 添加到您的视图来解决它

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

如果此方法不起作用。您将尝试在中间件中评论 csrf。并再次测试。

【讨论】:

    【解决方案5】:

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

    所以我的代码是这样的:

    urlpatterns += path('resource', ResourceView) 
    

    它应该是这样的:

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

    【讨论】:

    • 哇,这就是我的情况。我忘了加()
    【解决方案6】:

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

    【讨论】:

    • 如果你也包含一些代码会更好
    • @AlexJolig 刚刚遇到了同样的问题,问题是我忘记在我的 ApiView 之后添加.as_view() 所以代码看起来像:urlpatterns += path('resource', ResourceView) 它应该是这样的:urlpatterns += path('resource', ResourceView.as_view())
    【解决方案7】:

    尝试检查您是否已在 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 是表字段还是变量。
    • 是一个变量{{ account_num }},但是这对csrf token有什么影响呢?
    • 我相信 csrf 令牌只引用了 request ,因此它无法验证或处理这里的变量。检查 djangoproject.com 可能您可以获得有关 csrf_token 的正确答案。
    【解决方案8】:

    由于 Python 本身的一个错误,这个问题最近再次出现。

    http://bugs.python.org/issue22931

    https://code.djangoproject.com/ticket/24280

    受影响的版本包括 2.7.8 和 2.7.9。 如果其中一个值包含[ 字符,则无法正确读取 cookie。

    更新 Python (2.7.10) 解决了这个问题。

    【讨论】:

      【解决方案9】:

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

      <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">
      

      我的错误消失了。

      【讨论】:

        【解决方案10】:

        问题似乎是您没有适当地处理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))
        

        【讨论】:

          【解决方案11】:

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

          【讨论】:

            【解决方案12】:

            方法一:

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

            方法二:

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

            因为 render_to_response 方法可能会导致响应 cookie 的一些问题。

            【讨论】:

              【解决方案13】:

              清除浏览器的缓存为我解决了这个问题。在另一个项目发生后,我一直在本地开发环境之间切换以完成 django-blog-zinnia 教程。起初,我认为更改 INSTALLED_APPS 的顺序以匹配教程会导致它,但我将它们设置回来并且无法更正它,直到清除缓存。

              【讨论】:

                【解决方案14】:

                我之前使用的是 Django 1.10。所以我遇到了这个问题。 现在我将它降级到 Django 1.9 并且运行良好。

                【讨论】:

                • 使用 1.10.3 我遇到了这个问题。升级到 1.10.6 为我修复了它。
                【解决方案15】:

                我遇到了同样的错误,在我的情况下添加 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):
                    ...
                

                【讨论】:

                  【解决方案16】:

                  确保您的 django 会话后端在 settings.py 中正确配置。那就试试这个,

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

                  MIDDLEWARE_CLASSESMIDDLEWARE 下的settings.py 中添加此中间件,具体取决于django 版本

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

                  【讨论】:

                    【解决方案17】:

                    我刚遇到一次,解决办法是清空cookies。 并且在调试SECRET_KEY相关时可能会发生变化。

                    【讨论】:

                      【解决方案18】:

                      如果你没有在你正在渲染的模板中使用{% csrf_token %} 标签。 Django 不会设置 csrftoken cookie。

                      要强制 django 设置 csrftoken cookie,请在视图中添加 ensure_csrf_cookie 装饰器。

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

                      【讨论】:

                        【解决方案19】:

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

                        from django.views.decorators.csrf import csrf_protect

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

                        【讨论】:

                          猜你喜欢
                          • 2018-12-30
                          • 1970-01-01
                          • 2016-04-19
                          • 2016-03-16
                          • 2019-05-06
                          • 1970-01-01
                          • 2020-08-22
                          • 2020-09-10
                          相关资源
                          最近更新 更多