【问题标题】:Django : CSRF verification failed even after adding {% csrf_token %}Django:即使在添加 {% csrf_token %} 后,CSRF 验证也失败了
【发布时间】:2012-01-14 13:33:07
【问题描述】:

views.py:

def index(request):
    return render_to_response('index.html', {})

def photos(request, artist):
    if not artist:
        return render_to_response('photos.html', {'error' : 'no artist supplied'})
    photos = get_photos_for_artist(artist)
    if not photos:
        logging.error('Issue while getting photos for artist')
        return render_to_response('photos.html', {'error': 'no matching artist found'})
    return render_to_response('photos.html', {'photos': photos})  

Index.html:

<html>
    <head>
        <title>find artist photos </title>
    </head>
    <body>
        {% block error %} {% endblock %}
        <form action="/photos" method="POST">
            {% csrf_token %}
            <label for="artist">Artist : </label>
            <input type="text" name="artist">
            <input type="submit" value="Search">
        </form>
        {% block content %}{% endblock %}
    </body>
</html>

photos.html:

{% extends 'index.html' %}
{% block error %}
    {% if error %}
        <p> {{ error}} </p>
    {% endif %}
{% endblock %}

{% block content %}
    {% if photos %}
        {% for photo in photos %}
            {{ photo }}
        {% endfor %}
    {% endif %}
{% endblock%}

url.py:

urlpatterns = patterns('',
    (r'', index),
    (r'^time/$', current_datetime),
    (r'^photos/(\w+)$', photos)
)

我什至尝试添加{% csrf_token %},但没有成功

谢谢

更新
我在日志中看到了这些

UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.
  warnings.warn("A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.")  

这是在将 context_instance=RequestContext(request) **添加到 render_to_response()**

之后发生的

【问题讨论】:

    标签: python django


    【解决方案1】:

    context_instance=RequestContext(request) 添加到您将在其中使用表单的每个视图中:

    return render_to_response('index.html', {}, context_instance=RequestContext(request) )
    
    
    return render_to_response('photos.html', {'photos': photos}, context_instance=RequestContext(request) )
    

    【讨论】:

    【解决方案2】:

    假设您使用的是最新版本的 Django (1.3/1.4/dev),您应该按照以下步骤操作:

    • settings.py中,将中间件django.middleware.csrf.CsrfViewMiddleware添加到 MIDDLEWARE_CLASSES 列表。
    • 在您的模板中,使用表单中的{% crsf_token %}
    • 在您看来,请确保 django.core.context_processors.csrf 上下文处理器被以下任一者使用:
      • 使用RequestContext 来自django.template
      • 直接从from django.core.context_processors导入csrf处理器

    示例

    from django.template import RequestContext
    from django.shortcuts import render_to_response
    
    def my_view(request):
        return render_to_response('my_template.html', {}, context_instance=RequestContext(request))
    

    from django.core.context_processors import csrf
    from django.shortcuts import render_to_response
    
    def my_view(request):
        c = {csrf(request)}
        return render_to_response('my_template.html', c)
    

    参考文献

    (后人和未来观众的详尽帖子)

    【讨论】:

      【解决方案3】:

      这里有很多问题需要解决:

      • 请在网络浏览器中加载您的“索引”页面,执行“查看源代码”,并检查{% csrf_token %} 是否正在展开。它应该替换为&lt;input&gt; 标签。如果这没有发生,那么您的索引页有问题。如果它被正确替换,那么您的照片页面就有问题。

      • index.html 中的 POST URL 与 urls.py 中的任何模式都不匹配。您的 urls.py 似乎希望搜索词成为 URL 的一部分,但事实并非如此 - 您将其作为 HTTP POST 参数发送。您需要通过request.POST 访问它。

      【讨论】:

      • 好点。通常最好使用 GET 而不是 POST 方法进行搜索,因为它们可以被添加书签。所以我建议更改模板,而不是更改视图。其中一个确实需要更改。
      • 其实,这才是终极解决方案!我遇到了很多提到这个问题的文章,但只有这一篇指出了事实。请使用 Requestcontext 渲染索引页面。
      【解决方案4】:

      检查设置,如果你有这个中间件:

      'django.middleware.csrf.CsrfViewMiddleware'
      

      https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

      【讨论】:

      • 和上下文处理器'django.core.context_processors.csrf'?
      【解决方案5】:

      您可能需要在使用 render_to_response 时显式传入 RequestContext 实例,以获取该模板标签的 CSRF 值。

      http://lincolnloop.com/blog/2008/may/10/getting-requestcontext-your-templates/

      【讨论】:

        【解决方案6】:

        尝试使用@csrf_protect 装饰器:

        from django.views.decorators.csrf import csrf_protect
        from django.shortcuts import render_to_response
        
        @csrf_protect
        def photos(request,artist):
            if not artist:
                return render_to_response('photos.html', {'error' : 'no artist supplied'})
            photos = get_photos_for_artist(artist)
            if not photos:
                logging.error('Issue while getting photos for artist')
                return render_to_response('photos.html', {'error': 'no matching artist found'})
            return render_to_response('photos.html', {'photos': photos})  
        

        【讨论】:

        • 试过了,但在那种情况下它似乎没有调用照片功能,日志说 [06/Dec/2011 18:08:05] "GET / HTTP/1.1" 200 403 [ 2011 年 12 月 6 日 18:08:08]“POST /photos HTTP/1.1”200 403
        • 我猜你已经看到了:“默认情况下,如果传入的请求未通过 CsrfViewMiddleware 执行的检查,则会向用户发送 '403 Forbidden' 响应。通常只有在出现是真正的跨站点请求伪造,或者由于编程错误,CSRF 令牌未包含在 POST 表单中。”来自docs.djangoproject.com/en/dev/ref/contrib/csrf。似乎 CSRF 令牌没有以某种方式正确传输。
        • 如果将csrf_protect添加到索引视图中?
        • 我在索引和照片中都添加了@csrf_protect,但没有运气!我确定它的编程错误,但不确定在哪里
        【解决方案7】:

        这对我有用:

        {% csrf_token %} 在模板中,每个 POST 表单内都有一个 {% csrf_token %} 模板标签,以内部 URL 为目标。

        在views.py中:

        从 django.template 导入 RequestContext

        ...

        ...

        ...

        return render_to_response("home.html", {}, context_instance=RequestContext(request))

        【讨论】:

        • 不确定此答案如何添加已发布的答案尚未涵盖的内容?
        猜你喜欢
        • 2018-03-10
        • 1970-01-01
        • 1970-01-01
        • 2016-09-09
        • 2014-01-20
        • 1970-01-01
        • 2017-10-20
        • 2012-09-08
        • 2015-06-02
        相关资源
        最近更新 更多