【问题标题】:avoiding csrf error in django 1.4.3避免 django 1.4.3 中的 csrf 错误
【发布时间】:2013-02-15 15:08:44
【问题描述】:

我正在使用 django 设计一个基本的登录和注销页面。所以下面是我的代码

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...........
    ...........
    "django.contrib.messages.context_processors.messages",
    "django.core.context_processors.request",
    "django.core.context_processors.csrf",
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)
INSTALLED_APPS = (
    'django.contrib.auth',
    .......
    ....... 
)

urls.py

from django.conf.urls.defaults import *
from django.conf import settings

urlpatterns = patterns('',
             url(r'^$', 'learn_django.views.home_page'),          
             url(r'^login/$', 'learn_django.views.login'),
             url(r'^logged_in$', 'learn_django.views.logged_in'),
             url(r'^logout/$', 'learn_django.views.logout'),
)


if settings.DEBUG:
    urlpatterns = patterns('',
    url(r'^media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
) + urlpatterns

views.py

from django.shortcuts import render_to_response
from django.template import RequestContext

def home_page(request):
    return render_to_response("home_page.html")

def login(request):
    return render_to_response("login.html")

def logged_in(request):
    return render_to_response("logged_in.html",context_instance=RequestContext(request))

base.html

{% load staticfiles %}
<html xmlns="http://www.w3.org/1999/xhtml"> 
  <head>
    <link rel="stylesheet" href="{% static 'css/home_remaining.css' %}" type="text/css">
    <title>{% block title %}{% endblock %}</title>
  </head>
  <body>
   <header>
     <div class='header_div'>
       <div class="logout"><p id='logout'><a href="/logout" >Logout</a></p><div>
       <div class="login"><p id='login'> <a href="/login" >Login</a></p><div>
     </div>
   </header>
   <div class="body_content">
      {% block body %}{% endblock %}
   </div>
</body> 
</html>

login.html

{% extends 'base.html' %}
{% block title %}Login Page{% endblock %}
{% block body %}
  <div id='container'>
      <form action="/logged_in" method="POST">
         {% csrf_token %}
            <label for="name">Username:</label><input type="name">
            <label for="username">Password:</label><input type="password">
            <div id="lower">
                <input type="submit" value="Login">
            </div>
      </form> 
   </div>     
{% endblock %}

上面是我的完整代码,当我们点击base.html 中给出的Login 链接时,它会显示一个登录表单。

登录后显示并输入一些usernamepassword并单击Login按钮,显示一个错误页面,指出csrf error已经显示

google了很多,在表单标签里面添加了{% csrf_token %},还在settings.py的模板上下文过程中添加了django.core.context_processors.csrf

下面是错误消息的样子

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.

因此,当我从模板上下文进程中删除 django.core.context_processors.csrf 时,它的工作正常。但我也想使用 csrf 保护。

最后,实际上上面的视图代码有什么问题,为什么会出现 csrf 错误页面以及如何避免上面的错误页面?

我是否需要在我的views.py 函数中添加任何代码?

谁能在我上面的函数中添加基本的登录和注销功能代码,这样对代码的实际理解更有帮助......

已编辑

针对上述问题,我导入了如下的 csrf_exempt 函数

from django.views.decorators.csrf import csrf_exempt

并将其作为 logged_in 视图之前的装饰器,当我单击登录按钮时它不会显示错误页面

但仍然想知道为什么下面提到的方法(例如从模板发送 Requestcontext)不起作用

【问题讨论】:

标签: python django templates views csrf


【解决方案1】:

您需要将RequestContext 传递给您的render_to_response 函数。

def home_page(request):
    return render_to_response("home_page.html", context_instance=RequestContext(request))

或者使用新的渲染函数,它会为您处理传递RequestContext

def home_page(request):
    return render(request, "home_page.html")

RequestContext 将各种有用的东西添加到传递给模板的上下文字典中。这包括 csrf 令牌。请查看RequestContext docs 了解更多信息。

在您的情况下,您的 login 视图正在呈现 login.html 模板,但未传递 csrf 令牌。当login.html 模板回发到服务器(到/logged_in)时,logged_in 视图会检查该 csrf 令牌。它不存在(因为您从未包含它)。所以它假设它收到了一个跨站点请求伪造。

阅读csrf docs 以更了解该过程。

【讨论】:

  • 您仍然需要将request 传递给render()
  • 实际上问题不在于我访问主页时,而是当我单击登录按钮时,该按钮将请求发送到已发送的 Requestcontext 视图函数,如上所示对吗?
  • 您需要将 RequestContext 传递给您的所有 render_to_response 函数(或者至少是那些模板会将发布数据返回到服务器的视图中的函数)。将上面显示的模式复制到您的登录视图。
  • 您的登录视图正在呈现 login.html 模板,但未传递 csrf 令牌。当 login.html 模板回传到服务器(到 /logged_in)时,logged_in 视图会检查该 csrf 令牌。它不存在(因为您从未包含它)。所以它假设它收到了一个跨站点请求伪造。
  • 是的,我尝试在渲染时将 Requestcontext 复制到所有视图函数,并尝试单击登录按钮,但仍然无法正常工作并显示相同的 csrf 错误页面
猜你喜欢
  • 1970-01-01
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
相关资源
最近更新 更多