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

Python 将CSRF令牌添加到硬编码的Django表单,python,django,jekyll,csrf,Python,Django,Jekyll,Csrf,我正在用Jekyll构建一个具有硬编码表单的静态页面,我正在将表单数据发送到Django服务器,我在生成CSRF令牌时遇到问题。我能将数据保存到数据库的唯一方法是,如果我使用一个静态csrf令牌,这是有漏洞的、毫无意义的 有没有更好的方法可以做到这一点? 这就是我想要的: <form method="POST" action="http://djangoserver" > {% csrf_token %} <!-- Doesn't work in Jekyll --&g

我正在用Jekyll构建一个具有硬编码表单的静态页面,我正在将表单数据发送到Django服务器,我在生成
CSRF令牌时遇到问题。我能将数据保存到数据库的唯一方法是,如果我使用一个静态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>

{%csrf_令牌%}

您所尝试的是不可能的,使Jekyll静态页面具有某种动态性的唯一方法是使用javascript

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


希望这有帮助,
{%csrf\u token%}
不会工作,因为它是Django模板标记。硬编码csrfmiddlewaretoken也不起作用,因为此值会更改以提供安全性

我的博客上也有一个类似的问题,那就是杰基尔。在一个联系人页面上,我添加了一个普通的HTML表单,其中
action
指向我的Django后端。对于这个视图,我使用
@CSRF\u emption
装饰器删除了CSRF令牌验证

为了避免滥用,我添加了一个GoogleReCAPTCHA验证

请参见下面的示例:

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

如果这是而不是在同一个域上,我建议设置

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

添加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);

希望这能有所帮助。

聪明,没有想到这一点,因此表单位于一个域(GitHub页面)上,Django将托管在单独的主机上。我觉得js方法是最简单的,我是否可以在一台服务器上生成令牌并将其发送给Django,或者我必须为此制作api?我认为这是不可能的。如果可能的话,这不是一个好主意。在这种情况下,您应该在Django REST框架上阅读,并使用它为Django服务器创建API。然后您可以接受来自其他域名的请求。
// 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;
}
<form id="name-form" method="POST" action="http://djangoserver" >
    <input type="text" name="name" required id="id_name" maxlength="100>
</form>
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);