2010-11-27 113 views
5

我收到此消息:持久性「CSRF令牌丟失或不正確。」。 Jinja和Django註冊設置

CSRF令牌丟失或不正確。

在大多數論壇中,告訴你在窗體中獲得{%csrf_token%},並且我確實擁有它。

而且我在我的settings.py:

TEMPLATE_CONTEXT_PROCESSORS = (
"django.contrib.auth.context_processors.csrf", 
"django.contrib.auth.context_processors.auth", 
) 

我使用的神社,它似乎沒有使用CSRF,但後來我安裝的Django登記和我迷路了,因爲它似乎正在使用一些其他的觀點,我無法這麼說,他們不是我寫的,我不知道他們在哪裏。 「標準認證視圖」,因爲他們稱之爲。所以我無法添加「RequestContext」。

任何想法發生了什麼以及我如何才能實現? thanx

+0

你的模板是什麼樣的? – JonC 2010-11-27 21:18:48

+0

{%延伸 「site_base.html」 %} {%塊主體%} <形式方法= 「POST」 行動= 「/帳戶/登錄/」> \t {%csrf_token%} {{form.as_p} } {%endblock body%} – mgPePe 2010-11-27 22:21:23

回答

3

您可能需要手動重寫django註冊視圖。看起來像是issue with how Jinja likes to do things and how Django wants to configure template loaders.

要查看標準auth視圖,只需在python安裝中的「site-packages」下查看即可。

你可以嘗試包裝這樣的標準權威性的觀點:

from django.contrib.auth.views import login, logout 
from django.views.decorators.csrf import csrf_protect 

@csrf_protect 
def my_wrapped_login_view(request): 
    return login(request) 

@csrf_protect 
def my_wrapped_logout_view(request): 
    return logout(request) 

我基本上是進口的Django的標準權威性的意見,並要求他們與我自己的,這有csrf_protect裝飾。這值得一試。

+0

你的答案有點太複雜了,所以我將不得不一點一點地調查它,主要是如何設置自定義視圖。 thanx很多 – mgPePe 2010-11-27 22:55:48

2

您是否還安裝了標準的Django模板系統?大多數隨模板分發的應用程序都需要這樣做。

對於CSRF,上下文處理器將變量'csrf_token'插入到從中間件檢索的響應上下文中(如果啓用)。現在你所要做的就是確保它與你的表格不同。

這是直接出django.core,並隨時可能會發生變化。

 if csrf_token: 
      if csrf_token == 'NOTPROVIDED': 
       return mark_safe(u"") 
      else: 
       return mark_safe(u"<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='%s' /></div>" % csrf_token) 

然而,看到的是,你真正需要知道的是,你必須有一個名爲csrfmiddlewaretoken與context.get的值的輸入型窗體中(「csrf_token」,「」),這一切她寫了。

+0

我遇到了同樣的問題,如果在查看模板的源代碼時沒有看到名爲csrfmiddlewaretoken的輸入類型,會發生什麼情況? – juankysmith 2011-06-17 06:30:33

1

這個最直接的答案就是將{%csrf_token%}放在模板/ html中的表單標籤中。

-6

我只是關掉了CSRF中間件在設置像這樣,而現在它的工作原理:

#'django.middleware.csrf.CsrfViewMiddleware', 
2

這個答案是不特定於Django的註冊,只是使用Django與Jinja2的一般。

如果Django的CsrfViewMiddleware確定您已經訪問了csrf_token上下文成員,則會設置csrf_token cookie。不幸的是,直到Django的中間件執行之後,才發生Jinja2渲染。因此,Cookie不會被設置,因此與表單不匹配,您將得到403錯誤。

要解決此問題,需要在完成處理響應之前的某個時間訪問上下文['csrf_token']。

如果您正在使用基於類的意見,你可以創建一個CsrfProtectMixin:

class CsrfProtectMixin(object): 
    def render_to_response(self, context, **response_kwargs): 
     # Csrf processing happens when using a RequestContext. 
     # Be sure to use one. 
     if not isinstance(context, RequestContext): 
      context = RequestContext(self.request, context) 

     # Force access to csrf_token due to the way jinja2 renders the template 
     # after middleware has finished processing. Otherwise, the csrf cookie 
     # will not be set. 
     str(context.get('csrf_token')) 

     return super(CsrfProtectMixin, self).render_to_response(context, **response_kwargs) 

然後在您的視圖類:

class MyView(CsrfProtectMixin, TemplateView): 
    def get(self, request, *args, **kwargs): 
     context = {} 
     return self.render_to_response(context) 

如果你不使用類爲主意見,你可以做這樣的事情:

def my_view(request): 
    context = RequestContext(request) 
    str(context['csrf_token']) #force access to the csrf_token 
    return render_to_response('template.html', context) 

或者猴子補丁render_to_reponse與類中的邏輯,以上。