如何在POST-超链接中使用csrf-token?
How to use csrf-token in POST-hyperlink?
我需要在 Django 中为 POST 请求创建一个超链接。例如,菜单中的“添加到黑名单”。使用带有提交按钮的表单很容易,但我需要一个菜单项而不是按钮。我找到了执行此操作的 Javascript 代码,但它给我一个错误 403:CSRF 令牌丢失或不正确。而且我找不到关于如何将 csrf-token 插入 Javascript 函数的信息。我不知道Javascript,我写在Python.
这是来自 https://ru.whosebug.com/questions/65237/Вызов-метода-post-через-ссылку 的函数:
<script type="text/javascript">
function postToUrl(path, params, method) {
method = method || "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form.submit();
}
</script>
我是这样称呼它的:
<a href="#" onclick="postToUrl('/account/add_to_blacklist/watched_user_id{{ message.recipient.user.id }}/next={{ request.get_full_path }}', {}, 'POST');">To blacklist</a>
这是我的观点:
class AddToBlacklistView(View):
def post(self, request, watched_user_id, next_url=None, *args, **kwargs):
if not next_url:
next_url = '../profile.html/user_id{0}'.format(watched_user_id)
if request.user.is_authenticated:
try:
user = User.objects.select_related("profile").get(username=request.user)
watched_user = User.objects.select_related("profile").get(id=watched_user_id)
except User.DoesNotExist:
raise Http404
if watched_user.id == user.id:
return redirect(next_url)
if watched_user not in user.profile.blacklist.all():
user.profile.blacklist.add(watched_user)
user.save()
if watched_user.profile in user.profile.friends.all():
user.profile.friends.remove(watched_user.profile)
if user.profile in watched_user.profile.friends.all():
friendship = Friendship.objects.get(user=watched_user.profile, friend=user.profile)
if friendship.status != 3:
friendship.status = 2
friendship.save()
if watched_user in user.profile.bookmarks.all():
user.profile.bookmarks.remove(watched_user)
return redirect(next_url)
else:
return redirect(next_url)
我试过了,但没用:
<meta name="csrf-token" content="{{ csrf_token }}">
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
</script>
我也尝试将其作为参数传递,但没有帮助:
csrfmiddlewaretoken: '{{ csrf_token }}'
更新:
我还尝试为视图添加装饰器,但它继续抛出相同的错误:
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
@method_decorator(csrf_protect)
def post ...
我还在视图上尝试了 @method_decorator(ensure_csrf_cookie),该视图使用调用 Javascript 函数的 HTML 呈现页面,但我仍然收到 403 错误。
我也尝试了 https://docs.djangoproject.com/en/3.0/ref/csrf/ 中的这段代码,它继续抛出相同的 403 错误。
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();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
请帮帮我!
我在这里找到了解决方案:
submitting a hyperlink by GET or POST
我不得不修改它,因为在我的页面上有一个人的列表,每个人都有一个菜单:
<form id="myform1_{{ message.recipient.user.id }}" method="post" action="/account/add_to_blacklist/watched_user_id{{ message.recipient.user.id }}/next={{ request.get_full_path }}" >
{% csrf_token %}
</form>
<a href="#" onclick="document.getElementById('myform1_{{ message.recipient.user.id }}').submit();">Add to blacklist</a>
我需要在 Django 中为 POST 请求创建一个超链接。例如,菜单中的“添加到黑名单”。使用带有提交按钮的表单很容易,但我需要一个菜单项而不是按钮。我找到了执行此操作的 Javascript 代码,但它给我一个错误 403:CSRF 令牌丢失或不正确。而且我找不到关于如何将 csrf-token 插入 Javascript 函数的信息。我不知道Javascript,我写在Python.
这是来自 https://ru.whosebug.com/questions/65237/Вызов-метода-post-через-ссылку 的函数:
<script type="text/javascript">
function postToUrl(path, params, method) {
method = method || "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form.submit();
}
</script>
我是这样称呼它的:
<a href="#" onclick="postToUrl('/account/add_to_blacklist/watched_user_id{{ message.recipient.user.id }}/next={{ request.get_full_path }}', {}, 'POST');">To blacklist</a>
这是我的观点:
class AddToBlacklistView(View):
def post(self, request, watched_user_id, next_url=None, *args, **kwargs):
if not next_url:
next_url = '../profile.html/user_id{0}'.format(watched_user_id)
if request.user.is_authenticated:
try:
user = User.objects.select_related("profile").get(username=request.user)
watched_user = User.objects.select_related("profile").get(id=watched_user_id)
except User.DoesNotExist:
raise Http404
if watched_user.id == user.id:
return redirect(next_url)
if watched_user not in user.profile.blacklist.all():
user.profile.blacklist.add(watched_user)
user.save()
if watched_user.profile in user.profile.friends.all():
user.profile.friends.remove(watched_user.profile)
if user.profile in watched_user.profile.friends.all():
friendship = Friendship.objects.get(user=watched_user.profile, friend=user.profile)
if friendship.status != 3:
friendship.status = 2
friendship.save()
if watched_user in user.profile.bookmarks.all():
user.profile.bookmarks.remove(watched_user)
return redirect(next_url)
else:
return redirect(next_url)
我试过了,但没用:
<meta name="csrf-token" content="{{ csrf_token }}">
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
</script>
我也尝试将其作为参数传递,但没有帮助:
csrfmiddlewaretoken: '{{ csrf_token }}'
更新: 我还尝试为视图添加装饰器,但它继续抛出相同的错误:
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
@method_decorator(csrf_protect)
def post ...
我还在视图上尝试了 @method_decorator(ensure_csrf_cookie),该视图使用调用 Javascript 函数的 HTML 呈现页面,但我仍然收到 403 错误。
我也尝试了 https://docs.djangoproject.com/en/3.0/ref/csrf/ 中的这段代码,它继续抛出相同的 403 错误。
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();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
请帮帮我!
我在这里找到了解决方案: submitting a hyperlink by GET or POST
我不得不修改它,因为在我的页面上有一个人的列表,每个人都有一个菜单:
<form id="myform1_{{ message.recipient.user.id }}" method="post" action="/account/add_to_blacklist/watched_user_id{{ message.recipient.user.id }}/next={{ request.get_full_path }}" >
{% csrf_token %}
</form>
<a href="#" onclick="document.getElementById('myform1_{{ message.recipient.user.id }}').submit();">Add to blacklist</a>