我已经制作了这样的局部视图(位置:MyController/_Form.cshtml
):
<form asp-antiforgery="true">
<input type="button" value="submit" />
</form>
Controller中的一些操作:
[HttpPost, ValidateAntiForgeryToken]
public IActionResult Test()
{
return Ok(new { succeeded = true });
}
[HttpPost]
public IActionResult GetTemplate()
{
string template = _viewRender<string>("MyController/_Form", null);
return Ok({ template = template });
}
_viewRender是一项将部分视图转换为字符串的服务。
我已经测试了这些步骤:
使用jquery从客户端向服务器发出请求以获取模板并附加到某个div。
let onSuccess = function (data) {
$(data.template).appendTo('.myDiv');
};
$.ajax({
url: '/MyController/GetTemplate',
method: 'POST'
}).done(onSuccess).fail(onError);
检测提交表单的事件如下:
$(document).on('click', 'input[type=text]', function () {
let _this = $(this);
let token = _this.parent().find('[name=__RequestVerificationToken]').val();
let onSuccess = function (data) {
console.log(data); // should be: Object:{succeeded:true}
};
$.ajax({
url: '/MyController/Test',
method: 'POST',
data: { __RequestVerificationToken: token },
processData: false,
contentType: false
}).done(onSuccess).fail(onError);
});
当我提出请求时,我总是在404 - not found
标签上收到错误代码Console
。
我确信路径是正确的。因此,我尝试从ValidateAntiForgeryToken
操作中移除Test
属性,然后再次尝试。它工作正常(请求状态代码200
)。
所以,我猜这个问题(给出了404错误)来自令牌。我已经使用开发人员工具再次检查,我确信我有一个令牌。但我不知道如何检查令牌是否有效。
令牌是从服务器生成的。我刚刚提出要求并将其附加到身体上。然后,将其重新发送到服务器。但服务器不接受它。
为什么?
答案 0 :(得分:2)
这就是在ASP.NET Core中完成的......
在Input observable: >--a--b--c--d--|
Signal observable: >------1---1-1-|
Count in buffer: !--1--21-2-121-|
Output observable: >------a---b-c-|
中,您需要设置防伪标题名称。
if(File.Exists("myLibrary.dll")
{
MyForm frm = new MyForm();
frm.ShowDialog();
}
您需要这样做,因为默认情况下,防伪只会考虑表单数据,我们希望它也能与ajax一起使用。
在您的Startup.cs
文件中,您需要添加services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
,这将使用验证令牌呈现隐藏的输入。
最后在您的ajax代码中,您需要在发送之前设置请求标头。
.cshtml
因此,在您的情况下,ajax代码将如下所示。
@Html.AntiForgeryToken()
答案 1 :(得分:0)
两件事。
首先,我使用自定义过滤器而不是ValidateAntiForgeryToken。我不记得为什么。可能ValidateAntiForgeryToken不能处理AJAX请求。
这是我使用的自定义过滤器的代码。
[AttributeUsage(AttributeTargets.Class)]
public sealed class ValidateAntiForgeryTokenOnAllPostsAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException(nameof(filterContext));
}
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie?.Value;
AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
}
}
}
}
其次,令牌进入请求头而不是数据部分。我使用布局文件中的ajaxSetup将其添加到标头中。这样我就不用担心记得将它添加到每个AJAX请求中。
$.ajaxSetup({
cache: false,
headers: { "__RequestVerificationToken": token }
});