首页 文章

Django 1.8格式错误后没有CSRF令牌

提问于
浏览
0

我最近将我的网站升级到Django 1.8,当我的注册(用户注册)表单发布时,我得到"ImportError No module named lib" . 具体来说,如果用户正在注册帐户并且他们的密码不匹配,我的form将显示错误 . 如果他们输入匹配的密码,我得到以下Django错误:

Request Method: POST
Request URL: http://localhost:8000/create_account/

Django Version: 1.8.4
Python Version: 2.7.5
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'account',
 'home',
 'members',
 'profile']
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware')

Traceback:
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  125.                     response = middleware_method(request, callback, callback_args, callback_kwargs)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in process_view
  189.                 return self._reject(request, REASON_BAD_TOKEN)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in _reject
  101.         return _get_failure_view()(request, reason=reason)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in _get_failure_view
  33.     return get_callable(settings.CSRF_FAILURE_VIEW)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/utils/lru_cache.py" in wrapper
  101.                     result = user_function(*args, **kwds)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/core/urlresolvers.py" in get_callable
  112.             if submod and not module_has_submodule(import_module(parentmod), submod):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py" in import_module
  37.     __import__(name)

Exception Type: ImportError at /create_account/
Exception Value: No module named lib

正如您在堆栈跟踪中看到的那样,当表单以匹配的密码发布时,中间件的响应被视为无效,然后控制甚至返回到显示表单的create_account视图 . 我在urlresolvers.py模块中设置了一个断点,发现无法找到的模块是“lib.local_csrf” . 我应该补充说,表单本身由signin(身份验证)表单和相关的注册(注册)表单组成,两个表单都包含csrf_token标记:

# home/templates/home.html
<form action="{% url 'sign-in' %}" method="post">
    {% csrf_token %}

    <!-- error fields appear here -->
    {% for field in sign_in_form.visible_fields %}
        {{ field.label_tag }}
        {{ field }}

    <input type="submit" value="Sign in">
    <a href="#">Forgot password?</a>
</form>

<form action="{% url 'create-account' %}" method="post">
    {% csrf_token %}

    <!-- error fields appear here -->
    {% for field in create_account_form.visible_fields %}
        {{ field.label_tag }}
        {{ field }}
    {% endfor %}

    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}

    <input type="submit" value="Sign up">
</form>

这是create_account视图:

# account/views.py
def create_account(request, template):
    # Initialize the signin form on the same page.
    sign_in_form = SignInAuthenticationForm(request, label_suffix="")

    if request.method == "POST":
        create_account_form = CreateAccountForm(request.POST, label_suffix="")
        if create_account_form.is_valid():
            user = User.objects.create_user(
                username = create_account_form.cleaned_data['username'],
                password = create_account_form.cleaned_data['password1']
            )

            # Create a new account.
            account = Account(user=user)
            account.save()
            # Do other stuff and then redirect user to next form
    else:
        create_account_form = CreateAccountForm(label_suffix="")
    return render_to_response(template, locals())

最有趣的是,当我在django.middleware.csrf中的process_view中设置断点时,当用户最初提交具有不匹配密码的表单时,csrf_token和request_csrf_token变量都包含相同的值 . 但是当他们输入匹配的密码并再次重新提交表单时,csrf_token包含令牌值,但request_csrf_token为空 . 事实证明,当用户重新提交表单时,request.POST ['csrfmiddlewaretoken']不在request.POST字典中 . 我不明白为什么会这样 .

这种形式在Django 1.6中运行得非常好,但它在1.8(或可能是1.7)中停止工作 . 我查看了1.7和1.8发行说明,没有看到CSRF功能的任何更改 . 我还阅读了与CSRF相关的模板文档,并没有看到任何新内容 . 对此错误进行在线搜索也没有出现任何问题 .

我怀疑你们中的一些人会建议我使用django-registration-redux库 . 由于我的注册工作流程,我认为我不能使用它 . 您可以看到,在用户在此表单上注册后,他们会在输入用户 Profiles 时首先重定向到某个页面,然后再转到可以上传照片的页面,然后再转到页面以查看和批准他们的 Profiles 和照片 . 之后,它们被转发到我的支付处理器 . 如果我的付款处理商告诉我他们的付款方式已获批准,他们只能使用有效帐户进行真正注册 .

谢谢 .

1 回答

  • 1

    实际错误 No module named lib 似乎是因为Django无法导入您在设置中指定的 CSRF_FAILURE_VIEW . 你可以尝试从你的设置中删除它,然后Django应该显示默认的CSRF失败页面而不是错误 . 我可以't tell why the import is failing, because you haven'显示 CSRF_FAILURE_VIEW 或您的项目结构 .

    要修复CSRF错误,请尝试使用render快捷方式而不是 render_to_response . 它使用请求上下文呈现模板,以便csrf_token标记起作用 .

    # avoid locals() if possible!
    return render(request, template, {...})
    

相关问题