繁体   English   中英

将 CSRF 令牌添加到硬编码的 Django 表单中

[英]Add CSRF token to hard coded Django form

我正在使用 Jekyll构建一个具有硬编码表单的静态页面,我正在将表单数据发送到 Django 服务器,我在生成CSRF token时遇到问题。 我可以将数据保存到数据库的唯一方法是使用静态 csrf 令牌,它既笨拙又毫无意义。

有没有更好的方法可以做到这一点?

这就是我要的:

<form method="POST" action="http://djangoserver" >
    {% csrf_token %} <!-- Doesn't work in Jekyll -->
    <input type="text" name="name" required id="id_name" maxlength="100>
 </form>

但显然 Jekyll 不知道那个令牌是什么,并且 POST 不会将它发送到 Django 服务器。


这是有效的,但它很容易受到攻击和hacky,我需要每次实际生成唯一令牌的相同效果。

<form method="POST" action="http://djangoserver" >
    <input type="hidden" name="csrfmiddlewaretoken" value=" some long stuff" >
    <input type="text" name="name" required id="id_name" maxlength="100>
 </form>

{% csrf_token %}不起作用,因为它是一个 Django 模板标签。 硬编码csrfmiddlewaretoken也不起作用,因为此值已更改以提供安全性。

我在我的博客 Jekyll 上也有类似的问题。 在联系页面上,我添加了普通的 HTML 表单,其中的action指向我的 Django 后端。 对于此视图,我使用@csrf_exempt装饰器删除了 CSRF 令牌验证。

为了避免滥用,我添加了 Google Recaptcha 验证。

请参阅下面的示例:

from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
import requests  # http://docs.python-requests.org

@require_POST
@csrf_exempt
def ask(request):
    recaptcha_response = request.POST.get('g-recaptcha-response')
    data = {
        'secret': settings.GOOGLE_INVISIBLE_RECAPTCHA_SECRET_KEY,
        'response': recaptcha_response
    }
    r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
    result = r.json()

    if result['success']:
        # process form...
    else:
        # invalid recaptcha

您正在尝试的是不可能的,使 Jekyll 静态页面有点动态的唯一方法是使用 JavaScript。

您可以通过在 Django 中创建 API 来实现您想要的内容,该 API 将创建 CSRF 令牌并返回它,然后您可以将其附加到您的表单中。 这样您将始终拥有动态 CSRF,但是我不建议通过网络发送 CSRF 令牌,因为它不安全。

如果这不在同一个域中,我建议设置Django REST Framework

如果它在同一个域中,则执行Django Docs上的建议:您可以使用 JavaScript 获取 CSRF 令牌(请注意,我已将函数更改为不使用 jQuery):

// WITHOUT jQuery
function getCookie (name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

更新表单(注意id ):

<form id="name-form" method="POST" action="http://djangoserver" >
    <input type="text" name="name" required id="id_name" maxlength="100>
</form>

添加 csrftoken 输入:

var form = document.getElementById('name-form'),
    input = document.createElement('input');

input.name = "csrfmiddlewaretoken";
input.type = "hidden";
input.value = getCookie('csrftoken');
// ^ could be a different string depending on your settings.py file

form.appendChild(input);

希望有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM