python - 禁止 (403) CSRF 验证失败。请求中止。即使使用 {% csrf_token %}

标签 python django authentication csrf django-csrf

我正在尝试在 django 中登录,但出现此错误,我检查了 CSRF 文档,但没有任何用处。

这里是 HTML:

<body>
  <section class="container">
    <div class="login">
      <h1>Login to Web App</h1>

      {% if form.errors %}
        <p class="error">Lo sentimos, la combinacion de usuario y contrasena no es correcta!</p>
      {% endif %}  

      <form action="/accounts/auth/" method="post">
      {% csrf_token %}  
      <input type='hidden' name='csrfmiddlewaretoken' value='randomchars'/>

        <p><input name="username" type="text" name="login" value="" placeholder="Username"></p>

        <p><input name="password" type="password" name="password" value="" placeholder="Password"></p>

        <p class="submit"><input type="submit" name="commit" value="Login"></p>
      </form>
    </div>
</body>

如您在上面看到的,我使用 {% csrf_token %} 并且在我安装的应用程序中有“django.middleware.csrf.CsrfViewMiddleware”。

我的观点是:

from django.http import HttpResponse,HttpResponseRedirect
from django.template.loader import get_template 
from django.template import Context
from datetime import datetime
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf

from models import *
from django.shortcuts import get_object_or_404
from forms import *
from django.template.context import RequestContext
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login

def login(request):
    c = {}
    c.update(csrf(request))
    return render_to_response('login.html', c)    


def auth_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        auth.login(request.user)
        return HttpResponse('/accounts/loggedin') 
    else:
        return HttpResponse('/accounts/invalid')

我重定向到另一个我不使用 {% csrf_token %} 的 HTML 文件。

最佳答案

理论


要使 csrf 保护起作用,需要做一些事情(查看 docs):

  1. 您的浏览器必须接受来自您服务器的 cookie
  2. 确保您拥有 ' django.middleware.csrf.CsrfViewMiddleware'作为中间件包含在您的settings.py 中(或者在要保护的特定 View 上使用装饰器 csrf_protect())
  3. 确保从 django.core.context_processors.csrf 传递 csrf token 到上下文管理器。

当您加载页面时,请使用您喜欢的浏览器查看页面源代码。不要打开模板 html 文件,打开指向包含表单的 View 的 url。查看您放置 {% csrf_token %} 的位置.如果你看到类似的东西

<input type='hidden' name='csrfmiddlewaretoken' value="jdwjwjefjwdjqwølksqøwkop2j3ofje" />

你应该没事的。

另一方面,如果您看到 NOTPROVIDED ,创建 csrf token 时出现问题。通过查看源代码( context_processors.pycsrf.py ),我们可以发现:

  • csrf(request)返回 {'csrf_token': 'NOTPROVIDED'}如果 get_token(request)返回无。
  • get_token(request)返回 request.META.get("CSRF_COOKIE", None) .

我假设这意味着它将返回 None如果 cookie 没有成功创建。

修复


对你来说,这意味着你应该先替换

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

<form action="/accounts/auth/" method="post">
{% csrf_token %}
(...)
</form>

我们希望 csrf 字段位于 <form>...</form> 内,而不是里面 <form> .由于目前的代码,它将被转换为

<form action="/accounts/auth/" method="post" <input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />>

我们更愿意

<form action="/accounts/auth/" method="post">
<input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />

之后 - 查看源代码,看看是否可以找到 csrf 字段。如果你能看到它,理论上一切都应该有效。

您还可以检查是否已在浏览器中设置 csrf cookie,例如在 Chrome 中,右键单击网页,然后选择 Insepect Element .选择Resources选项卡,然后单击 cookie。您应该找到一个 cookie 名称 csrftoken在那里。

如果仍有问题,请仔细检查 settings.py 中的中间件元组。并仔细检查您的浏览器是否接受来自您的服务器的 cookie,如上所述。

关于python - 禁止 (403) CSRF 验证失败。请求中止。即使使用 {% csrf_token %},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20895526/

相关文章:

python - Django 一致的自定义日志格式

当检索到的电子邮件与现有用户的电子邮件匹配时,django allauth facebook 重定向到注册?

python - 如何在 Python 中对 Active Directory 服务器进行两阶段身份验证?

Python - 字典中的重复值

python - 安装工具 - 传送附加文件

python - 将多个元组转换为嵌套字典

django - 默认创建非事件用户(is_active default False)

python - 有没有一个Python函数可以获取真实社区?

authentication - 使用 Torii 和 Simple-Auth : no authentication data returned 登录 Facebook

asp.net - 将 Facebook 身份验证与现有的 ASP.NET 成员资格集成