【问题标题】:CSRF verification failed. Request aborted - Serving a Django template as Server-Side IncludeCSRF 验证失败。请求中止 - 将 Django 模板作为服务器端包含服务
【发布时间】:2014-04-01 17:35:42
【问题描述】:

我已经在这里呆了几个小时了。我对 Django 比较陌生,我需要一些看起来并不常见的设置方面的帮助。

我正在使用 Nginx 和 UWSGI 为我的网站提供服务,其中大多数页面都是静态的,而不是使用 Django 提供服务。我使用 Django 的唯一原因是为了实现一个表单。因此,我决定将表单模板本身 SSI 到 Django 服务器外部现有 HTML 中的

中。当 DEBUG = True 时,表单实际上工作得很好,但是当 False 时,表单会呈现,但在尝试提交时会抛出错误。错误是“禁止 (403) CSRF 验证失败。请求中止。失败原因:未设置 CSRF cookie。”现在我找到的解决方案只假设整个网站由 Django 提供服务。然而,对我来说,只有一个 Django 模板的 sn-p 是使用 Nginx 的 SSI 提供的。我想知道问题是什么以及社区是否可以帮助我。提前致谢!
HTML outside of Django:  
<div id="formContainer"><!--#include virtual="/webform/contact/" --></div>

#Django view
def contact(request):
    if request.method == 'POST': # If the form has been submitted...
        form = ContactForm(request.POST) # A form bound to the POST data

    if form.is_valid(): #All validation rules pass
        # Process the data in form.cleaned_data
        firstName = form.cleaned_data['firstName']
        lastName = form.cleaned_data['lastName']
        street = form.cleaned_data['street']
        city = form.cleaned_data['city']
        state = form.cleaned_data['state']
        zipcode = form.cleaned_data['zipcode']
        phone = form.cleaned_data['phone']
        email = form.cleaned_data['email']
        message = form.cleaned_data['message']

        request.session['fname_ses'] = firstName
        request.session['lname_ses'] = lastName
        request.session['street_ses'] = street
        request.session['city_ses'] = city
        request.session['state_ses'] = state
        request.session['zip_ses'] = zipcode
        request.session['phone_ses'] = phone
        request.session['email_ses'] = email
        request.session['phone_ses'] = phone
        request.session['email_ses'] = email
        request.session['message_ses'] = message

        subject = "A message for _____ from %s %s" %(firstName, lastName)
        message_body = ("Here is the personal information provided by the client: \n"
            "      Full name: %s %s \n"
            "      Address: %s, %s, %s %s \n"
            "      Phone: %s \n"
            "      Email: %s \n \n"
            "Message to you: \n \n%s"
            %(firstName, lastName, street, city, state, zipcode, phone, email, message)
            )
        sender = "email1@example.com"
        recipients = [
            'email1@example.com',
            'email2@example.com',
             email3@example.com',
            ]

        from django.core.mail import send_mail
        send_mail(subject, message_body, sender,
            recipients, fail_silently=False)

        #Redirect after POST
        #reverse() redirects straight to the view instead of the URL
        #Use reverse() to prevent URL from appending to current address
        return HttpResponseRedirect('webform/thanks_simple.html')
        #return HttpResponseRedirect(reverse('webform:thanks'))
else:
    form = ContactForm() # An unbound form
return render(request, 'webform/contact.html', {'form': form,})

#contact.html within Django
    <p>We welcome your questions & comments</p>
    <p>Please fill out the form below and hit 'Submit'</p>
    <form action="{% url 'webform:contact' %}" method="post">
        {% csrf_token %}
        {{ form.non_field_errors }}
            <table>
                        <tr><th><label for="id_firstName">First Name:</label></th><td>{{ form.firstName.errors }} {{ form.firstName }}</td></tr>
                        <tr><th><label for="id_lastName">Last Name:</label></th><td>{{ form.lastName.errors }} {{ form.lastName }}</td></tr>
                        <tr><th><label for="id_street">Street:</label></th><td>{{ form.street.errors }} {{ form.street }}</td></tr>
                        <tr><th><label for="id_city">City:</label></th><td>{{ form.city.errors }} {{ form.city }}</td></tr>
                        <tr><th><label for="id_state">State:</label></th><td>{{ form.state.errors }} {{ form.state }}</td></tr>
                        <tr><th><label for="id_zipcode">Zipcode:</label></th><td>{{ form.zipcode.errors }} {{ form.zipcode }}</td></tr>
                        <tr><th><label for="id_phone">Phone:</label></th><td>{{ form.phone.errors }} {{ form.phone }}</td></tr>
                        <tr><th><label for="id_email">Email:</label></th><td>{{ form.email.errors }} {{ form.email }}</td></tr>
                        <tr><th><label for="id_message">Message:</label></th><td>{{ form.message.errors }} {{ form.message }}</td></tr>
            </table>
        <p><input type="submit" value="Submit" /></p>
    </form>

更新:Django returning 403 Error -- "CSRF cookie not set"

我发现了这个可行的解决方案,并决定对这些视图禁用 CSRF 保护。我将继续看看我是否可以再次测试破坏该站点。完成后,我会将csrf_exempt 视为解决方案。理想情况下,最好保持保护状态,但我使用的表单并不真正需要它,而且我已经使用它太久了。

【问题讨论】:

    标签: python django nginx django-forms uwsgi


    【解决方案1】:

    这是一个用于表单视图的示例 django 模板 sn-p。确保表单标签中有 {% csrf_token %}。

    <form action="/webform/contact/" method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value="{% trans 'Create' %}" />
    </form>
    

    【讨论】:

    • 我更新了我的原始帖子以包含我的原始contact.html。感谢您的帮助,但这不是我遇到的问题。我知道将 csrf_token 放入表单中,并在我的视图中尝试了其他方法,例如 @ensure_csrf_token。我的问题是当我单击提交按钮时,它会将我带到 CSRF 错误页面,当我使用您的 sn-p 时仍然会出现这种情况。
    【解决方案2】:

    我认为原因是缓存页面没有返回 csrf 令牌 cookie,因此 csrf 中间件引发了找不到它的错误。 可见的解决方案是使用 JS ..: 即向服务器发送 ajax 请求,如果不存在则返回 csrftoken。 成功的 js 从响应头中获取 csrftoken,请参阅文档:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax 并将所有表单(我在每个页面上都有几个)csrfmiddlewaretoken 输入值更新到 csrf。 这是一次操作,因为下一次 csrf 令牌仍保留在 cookie 中。

    希望有更好的解决方案,但这个可行。

    【讨论】:

      猜你喜欢
      • 2012-12-07
      • 2015-03-08
      • 1970-01-01
      • 2014-02-03
      • 2016-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多