当使用POST方法访问Razor页面时出现400错误请求。

37

我的页面有...

@page "{candidateId:int}"

...和
@Html.AntiForgeryToken()

模型具有...

public void OnGet(int candidateId)
{

}

public void OnPost(int candidateId)
{

}

GET请求正常。这是我的AJAX请求...

$.ajax({
    type: "POST",
    url: "/Skills/" + candidateId,
    beforeSend: function (xhr) {

        xhr.setRequestHeader("XSRF-TOKEN",
            $('input:hidden[name="__RequestVerificationToken"]').val());
    },
    data: {

        name: 'hi mum'
    },

    success: function (response) {
    },
    failure: function (response) {

        alert(response);
    }
});

浏览器接收到无用的错误信息... 400 Bad Request。

我错过了什么?


400错误应该提供比这更多的信息。它显示了什么实际错误? - DavidG
我认为这不是通过 AJAX 调用实现的。 - Ian Warburton
响应选项卡显示:“响应没有可用数据”。它只是一个数字和单词“错误”。 :) - Ian Warburton
1
请检查页面的源代码。您是否生成了名为__RequestVerificationToken的隐藏输入? - Shyju
哦,是的,那就是问题所在。我复制的代码将其设置为表单集合中的标题而不是值。谢谢。 - Ian Warburton
显示剩余2条评论
1个回答

62

由于框架期望请求中包含RequestVerificationToken,以防止可能的CSRF攻击,因此您会收到400(错误请求)响应。如果您的请求中没有这些信息,框架将返回400错误请求。您当前的代码没有发送它。

请更改代码为:

headers:
{
    "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
},

这将向请求标头添加一个名为RequestVerificationToken的新项,当发起调用时,框架应该不会抛出400响应(假设你的视图代码生成了__RequestVerificationToken隐藏输入)。

您可以通过向视图/页面注入IAntiforgery实现并使用GetAndStoreTokens方法来使代码更加健壮。

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
    return Xsrf.GetAndStoreTokens(Model.HttpContext).RequestToken;
}
}

并且在你的 JavaScript 中调用这个 GetAntiXsrfRequestToken 函数来获取该值。

headers:
{
    "RequestVerificationToken": '@GetAntiXsrfRequestToken()'
},

您可能还想使用PageModel的CandidateId属性来创建url。例如:

url: "/Skills/@Model.CandidateId",

同样,您确实需要显式调用@Html.AntiForgeryToken()方法来生成令牌输入。使用没有动作属性值的POST方法表单将为您生成隐藏的输入。

<form method="post">
   <!-- your inputs-->
</form>

3
您收到了400(错误请求)响应,因为框架期望RequestVerificationToken作为已发布请求的一部分。我在哪里可以找到这个特定信息的文档?请发布一个链接。 - PussInBoots
3
我也遇到了同样的问题,我的表单中缺少了@Html.AntiForgeryToken()。 - Carl Verret
2
如果您需要接受来自外部站点的POST请求,但该站点无法包含防伪令牌,该怎么办? - mxmissile
16
您可以在您的PageModel上使用[IgnoreAntiforgeryToken(Order = 1001)]修饰符来忽略反伪造令牌的验证。了解更多信息,请访问:https://www.learnrazorpages.com/security/request-verification#opting-out - ajbeaven
我也在 Razor 页面的模型表单中缺失了 @Html.AntiForgeryToken()。 - Roshan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接