Javascript 如何在没有表单的情况下将AntiForgery令牌传递给控制器
我有这个jquery函数,我想向控制器传递一个antiforgery令牌以进行验证。然而,我当前的方法是返回一个错误400,不管我是通过标题还是通过正文传递它 我把这张空表格放在我的页面顶部Javascript 如何在没有表单的情况下将AntiForgery令牌传递给控制器,javascript,jquery,asp.net,asp.net-core,Javascript,Jquery,Asp.net,Asp.net Core,我有这个jquery函数,我想向控制器传递一个antiforgery令牌以进行验证。然而,我当前的方法是返回一个错误400,不管我是通过标题还是通过正文传递它 我把这张空表格放在我的页面顶部 @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "form" })) { @Html.AntiForgeryToken() } 这是jquery函数。我在标题和正文中有requestverificationtoken,但
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "form" }))
{
@Html.AntiForgeryToken()
}
这是jquery函数。我在标题和正文中有requestverificationtoken,但它不起作用
$("#eventGenerateButton").on("click", function (e) {
e.preventDefault();
var event_form_data = {
"__RequestVerificationToken": token,
"StartDate": $("#eventStartDate").val(),
"EndDate": $("#eventEndDate").val(),
};
$.ajax({
url: "@Url.Action("GenerateEventLogsReport", @ViewContext.RouteData.Values["controller"].ToString())",
method: "POST",
headers: { "__RequestVerificationToken": token},
xhrFields: {
responseType: 'blob'
},
data: JSON.stringify(event_form_data),
contentType: "application/json",
success: function (result) {
GenerateReport(result,"EventLogs");
},
error: function (error) {
console.log(error);
}
});
return false;
});
这是控制器
[HttpPost]
[ValidateAntiForgeryToken]
public FileResult GenerateEventLogsReport([FromBody]GenericReportDateViewModel Input)
{
}
尝试将控制器签名更改为:
public FileResult GenerateEventLogsReport(string __RequestVerificationToken, string StartDate, string EndDate)
{
}
从
事件表单数据中删除令牌,然后尝试发送请求头,如
var event_form_data = {
"StartDate": $("#eventStartDate").val(),
"EndDate": $("#eventEndDate").val(),
};
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
url: "/Home/AjaxPost",
method: "POST",
headers: { "RequestVerificationToken": token},
xhrFields: {
responseType: 'blob'
},
data: JSON.stringify(event_form_data),
contentType: "application/json",
success: function (result) {
},
error: function (error) {
console.log(error);
}
});
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
AllowMultiple=false,Inherited=true)]
///此属性用于验证antiforgery,无论它是如何发送的。
///它不在乎标记是在头中还是在正文中,正文可以字符串化。
公共密封类MyValidateAntiForgeryAttribute:FilterAttribute,IAAuthorizationFilter
{
授权时的公共无效(AuthorizationContext filterContext)
{
如果(filterContext==null)
{
抛出新ArgumentNullException(“filterContext”);
}
var httpContext=filterContext.httpContext;
/*注意:防伪标识从一个页面传递两次,从一个页面传递一次
*帖子本身,并一度作为cookie进行验证
*值不匹配。它们是一个整体的两部分,并且都得到
*传递到验证例程中*/
var cookie=httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
//先试试页眉
var-token=httpContext.Request.Headers[“uu-RequestVerificationToken”];
//尝试正常方法
if(标记==null)
{
for(int cl=0;cl
在以下情况下,您无法使用股票验证器验证防伪令牌:
json被序列化
你在标题中传递它
您可以在url中传递它
如果您需要执行上述任何操作,您需要编写自己的反伪造检查,以便在传递的数据中找到令牌。
我已经写了一份防伪检查,检查内容如下:
检查url中的令牌
在序列化数据中检查它
在标题中检查它。
请随意使用它。请注意,这(故意)并不是筛选出GET。如果您在类级别添加它,您可能需要添加它
嗯?它甚至不会命中控制器签名,因为它未能通过[ValidateAntiForgeryToken]部分。如何获取令牌
?并确保数据正确。var token=$('input[name=“\uu RequestVerificationToken”]”)。val();这就是我得到它的方式。很抱歉迟到了。它在我的本地运行得很好。。你能分享一个可复制的演示吗?这甚至有效吗?控制器中的反伪造检查默认情况下会忽略标题,并且正在寻找一个以_uu开头的密钥
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
AllowMultiple = false, Inherited = true)]
///this attribute is for validating antiforgery, no matter how it's sent.
///It doesn't care if the token is in the header or body, and the body can be stringified.
public sealed class MyValidateAntiForgeryAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
var httpContext = filterContext.HttpContext;
/* Note: Antiforgery tokens are passed twice from a page. Once from
* the post itself, and once as a cookie to verify against it. The
* values do not match. They are two halves of a whole and both get
* passed into the validation routine. */
var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
//try header first
var token = httpContext.Request.Headers["__RequestVerificationToken"];
//try normal method
if (token == null)
{
for (int cl = 0; cl < httpContext.Request.Form.Keys.Count; cl++)
{
if (httpContext.Request.Form.Keys[cl] == "__RequestVerificationToken")
{
token = httpContext.Request.Form[httpContext.Request.Form.Keys[cl]];
}
}
}
//try url
if (token == null)
{
for (int cl = 0; cl < httpContext.Request.QueryString.Keys.Count; cl++)
{
if (httpContext.Request.QueryString.Keys[cl] == "__RequestVerificationToken")
{
token = httpContext.Request.QueryString[httpContext.Request.QueryString.Keys[cl]];
}
}
}
/* if still null, check to see if it's in a json string.
this section will retrieve the token out of a serialized dataset.
*/
if (token == null)
{
string json;
var position = httpContext.Request.InputStream.Position;
using (var reader = new StreamReader(httpContext.Request.InputStream, Encoding.UTF8, false, 8192, true))
{
json = reader.ReadToEnd();
//you MUST reset the input stream to start or you will break post.
httpContext.Request.InputStream.Seek(position, SeekOrigin.Begin);
try
{
var jsonObj = Json.Decode(json); //attempt to parse into json object.
token = jsonObj["__RequestVerificationToken"];
}
catch
{
//eat the parse errors. That simply means it's not json.
}
}
}
AntiForgery.Validate(cookie?.Value, token);
}
}