如何为Jekyll静态页面的硬编码表单添加Django CSRF Token?
Alright, let's figure out how to fix this CSRF token problem between your Jekyll static site and Django backend. Hardcoding that token is definitely a risky shortcut—here are some proper, secure ways to get the token dynamically so your POST requests work as intended:
1. Fetch a Fresh CSRF Token from Django via AJAX
Since Jekyll can't parse Django template tags, we'll create a simple Django endpoint to serve the CSRF token, then use JavaScript on your static page to grab it and inject it into the form.
Step 1: Add a Django View to Serve the CSRF Token
First, add this view to your Django app (make sure to wire it up in your urls.py):
from django.middleware.csrf import get_token from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def get_csrf_token(request): # Generate and return the current CSRF token for the session token = get_token(request) return JsonResponse({'csrfToken': token})
Step 2: Inject the Token into Your Jekyll Form
Add this JavaScript to your static page (replace your-form-id and the endpoint URL with your actual values):
document.addEventListener('DOMContentLoaded', function() { // Fetch the token from Django fetch('/api/csrf-token/', { credentials: 'include' // Critical: Ensures cookies are sent with the request }) .then(response => response.json()) .then(data => { // Create a hidden input for the CSRF token const csrfInput = document.createElement('input'); csrfInput.type = 'hidden'; csrfInput.name = 'csrfmiddlewaretoken'; // Django's required parameter name csrfInput.value = data.csrfToken; // Add it to your form const form = document.getElementById('your-form-id'); form.appendChild(csrfInput); }); });
2. Extract the CSRF Token from Django's Cookie
Django automatically sets a csrftoken cookie for users visiting your site. You can read this cookie directly with JavaScript and inject it into your form.
JavaScript to Extract and Inject the Token
Add this script to your Jekyll page:
// Helper function to get a cookie by name function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } document.addEventListener('DOMContentLoaded', function() { const csrfToken = getCookie('csrftoken'); const form = document.getElementById('your-form-id'); // Create and add the hidden CSRF input const csrfInput = document.createElement('input'); csrfInput.type = 'hidden'; csrfInput.name = 'csrfmiddlewaretoken'; csrfInput.value = csrfToken; form.appendChild(csrfInput); // Optional: If submitting via AJAX, you can send the token in the request header instead // form.addEventListener('submit', function(e) { // e.preventDefault(); // fetch('/your-django-form-endpoint/', { // method: 'POST', // credentials: 'include', // headers: { // 'X-CSRFToken': csrfToken, // 'Content-Type': 'application/x-www-form-urlencoded' // }, // body: new FormData(form) // }); // }); });
Critical Pitfalls to Avoid
- Cross-Origin Configuration: If your Jekyll site is hosted on a different domain than Django, install
django-cors-headersin your Django project, add it to middleware, and set:CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINS = ["https://your-jekyll-domain.com"] CSRF_COOKIE_DOMAIN = ".your-domain.com" # Adjust to match your domain - Credentials Must Be Included: Always set
credentials: 'include'in your fetch requests—Django needs the session cookie to validate the CSRF token. - Don't Hardcode Tokens: CSRF tokens rotate per session, so hardcoding one will break for subsequent users/sessions and expose your site to CSRF attacks.
内容的提问来源于stack exchange,提问作者Jiroscopes

