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

时间:2018-02-17 21:48:15

标签: python django jekyll csrf

我正在构建一个带有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 Server。

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

<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>

3 个答案:

答案 0 :(得分:1)

{% 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

答案 1 :(得分:0)

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

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

希望有所帮助

答案 2 :(得分:0)

如果在同一个域中,我建议您设置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);

希望有所帮助。