django错误 – Reason given for failure: CSRF cookie not set.

今天练习django的form的提交。当提交表单的时候,出现了

Forbidden (403)

CSRF verification failed. Request aborted.

Help

Reason given for failure:

    CSRF cookie not set.
    

In general, this can occur when there is a genuine Cross Site Request Forgery, or when

Django’s CSRF mechanism
has not been used correctly. For POST forms, you need to ensure:

  • Your browser is accepting cookies.
  • The view function uses
    RequestContext
    for the template, instead of Context.
  • In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
  • If you are not using CsrfViewMiddleware, then you must use
    csrf_protect
    on any views that use the csrf_token template tag, as well as those that accept the POST data.

You’re seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to
False, and only the initial error message will be displayed.

You can customize this page using the CSRF_FAILURE_VIEW setting.

从网上查到很多人说

在settings.py里面的MIDDLEWARE_CLASSES 中加入

‘django.middleware.csrf.CsrfResponseMiddleware’,

但是我的问题还是依旧,可是很多人说他们的问题就是这样解决的。后来知道是因为他们用的是1.2的版本,而我用的1.4版本,

后来去到官网:

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

参照它说的:

To enable CSRF protection for your views, follow these steps:

  1. Add the middleware'django.middleware.csrf.CsrfViewMiddleware' to your list ofmiddleware classes,

    MIDDLEWARE_CLASSES
    . (It should comebefore
    CsrfResponseMiddleware if that is being used, and before anyview middleware that assume that CSRF attacks have been dealt with.)

    Alternatively, you can use the decoratordjango.views.decorators.csrf.csrf_protect on particular views youwant to protect (see below).

  2. In any template that uses a POST form, use the
    csrf_token
    tag insidethe
    <form> element if the form is for an internal URL, e.g.:

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

    This should not be done for POST forms that target external URLs, sincethat would cause the CSRF token to be leaked, leading to a vulnerability.

  3. In the corresponding view functions, ensure that the'django.core.context_processors.csrf' context processor isbeing used. Usually, this can be done in one of two ways:

    1. Use RequestContext, which always uses'django.core.context_processors.csrf' (no matter what yourTEMPLATE_CONTEXT_PROCESSORS setting). If you are usinggeneric views or contrib apps, you
      are covered already, since theseapps use RequestContext throughout.

    2. Manually import and use the processor to generate the CSRF token andadd it to the template context. e.g.:

      from django.core.context_processors import csrf
      from django.shortcuts import render_to_response
      
      def my_view(request):
          c = {}
          c.update(csrf(request))
          # ... view code here
          return render_to_response("a_template.html", c)
      

      You may want to write your own render_to_response wrapper thattakes care of this step for you.

The utility script extras/csrf_migration_helper.py can help to automate thefinding of code and templates that may need to be upgraded. It contains fullhelp on how to use it.

但是问题依旧,后来又看到另外一种方式在这个网站上:

o manually exclude a view function from being handled by either of the two CSRFmiddleware, you can use the
csrf_exempt decorator, found in thedjango.views.decorators.csrf module. For example:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')

Like the middleware, the csrf_exempt decorator is composed of two parts: acsrf_view_exempt decorator and a
csrf_response_exempt decorator, foundin the same module. These disable the view protection mechanism(CsrfViewMiddleware) and the response post-processing(CsrfResponseMiddleware)
respectively. They can be used individually ifrequired.

终于把这个问题解决了。

其实我是绕开了这个问题,因为django之所以引进CSRF是为了避免Cross Site Request Forgeries攻击,而上面的解决方法恰好禁止掉这个django的功能。所以日后还得仔细研究下,在不禁掉这个功能的前提下成功的提交表单。

版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.

    分享到:
This entry was posted in Python, Web and tagged , . Bookmark the permalink.

7 Responses to django错误 – Reason given for failure: CSRF cookie not set.

  1. lgxwqq111 says:

    mark
    也是用装饰器暂时解决掉了

  2. XIAOLINJAVA says:

    这种方式违反了django的初衷,正确的解决方案有两个:
    1.引入RequestContext:
    from django.shortcuts import render_to_response, get_object_or_404,
    from django.template import RequestContext

    def edit(request, id):
    publisher = get_object_or_404(Publisher, id=id)
    if request.method == 'POST':
    appForm = PublisherForm(request.POST, instance = publisher)
    if appForm.is_valid():
    publisher = appForm.save();
    publisher.save()
    return HttpResponseRedirect(reverse("index"))
    return render_to_response('books/edit.html', {'form': PublisherForm(instance = publisher)}, context_instance=RequestContext(request))
    2.使用render方式渲染页面:
    from django.shortcuts import render_to_response, get_object_or_404, render
    def edit(request, id):
    同上
    #return render_to_response('books/edit.html', {'form': PublisherForm(instance = publisher)}, context_instance=RequestContext(request))
    return render(request, 'books/edit.html', {'form': PublisherForm(instance = publisher)})

    • 回复 XIAOLINJAVA:
      你说的很对,这样确实违背了django设计csrf的初衷,你说的这种会测试下,先谢谢了。

    • John__wang says:

      回复 XIAOLINJAVA:
      感谢这位牛人!!解决了我的问题。
      代码:
      <form action='' method="post">
      {% csrf_token %}
      <table>
      {{form}}
      </table>
      <input type="submit" value=" 注 册 ">
      </form>
      ——-
      def register(request):
      if request.method == 'POST':
      form = UserCreationForm(request.POST)
      if form.is_valid():
      new_user = form.save()
      return HttpResponseRedirect('../testjQ')
      else:
      form = UserCreationForm()
      return render_to_response('register.html',{"form":form})

      问题:
      依据django出错界面提示加 了{%csrf_token%},还是报错

      我的解决过程是这样:
      1、在网上找了加'django.middleware.csrf.CsrfResponseMiddleware',无效,因为django1.4已经没有这个类了,后台提示:ImproperlyConfigured: Middleware module "django.middleware.csrf" does not define a "CsrfResponseMiddleware" class
      2、屏蔽csrf,
      @csrf_exempt
      def register(request):
      ……
      好用了,但是屏蔽功能不是最好的方法,应该利用django提供的功能,去保证安全。没看django的时候都不知道crsf什么意思。
      3、看到此贴牛人回复,更改了视图
      把最后一行返回改为render_to_response('register.html',{"form":form},context_instance=RequestContext(request))

      • John__wang says:

        回复 John__wang:
        感觉django提示的应该还是算准确的
        我出现的问题就是 get方式进入页面时render_to_response()时没有使用RequestContext去渲染,我觉得没有提交就不用RequestContext,结果产生了问题。

        得到的结论就是此类问题中,模板里应该有csrf_token,生成的页面里应该体现csrf_token的标签,通过查看网页源代码,看到生成的代码里有类似的东西就应该是没有问题了<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='hkMpPG9DzAE1jdLQC2S5n6xVYBLodOxD' /></div>

  3. fononafonona says:

    我使用的不禁用crsf的方法解决问题,如下:
    #view.py:
    from django.template import RequestContext
    return render_to_response('contact_form.html',{'errors':errors},context_instance=RequestContext(request))
    #contact_form.html:
    <FORM METHOD="POST" ACTION="/contact/">{% csrf_token %}
    可以参考此方法,希望都可以通过此方法解决问题。O(∩_∩)O!

Leave a Reply

Your email address will not be published. Required fields are marked *

*