你好,我正在关注this tutorial:
[我正在尝试发送包含AntiforgeryToken的Ajax请求。这是我的Ajax请求:
$(document).ready(function () {
@functions{
public string TokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
$('.z').on('click', function (event) {
event.preventDefault();
$.ajax({
url: "/DeviceUsage/Return",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: 'html',
headers: {
'RequestVerificationToken': '@TokenHeaderValue()'
},
data: JSON.stringify({ dev: { DeviceInstanceId: $('#DeviceInstanceId').val(), UserId: "1", StorageId: $('#StorageId').val() } }),
error: function (data) {
alert("wystąpił nieokreślony błąd " + data);
},
success: function (data) {
$('.modal-body').html(data);
}
})
})
});
这里是我的控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Return(DeviceUsage dev)
{
if(dev.StorageId==3)
{
ModelState.AddModelError("", "Nie można oddać na własne biurko");
ViewBag.StorageId = new SelectList(unitOfWork.storageRepository.Get(), "Id", "Name", dev.StorageId);
return PartialView(dev);
}
dev.UserId = 1;
unitOfWork.deviceUsageRepository.Update(dev);
unitOfWork.Save();
return RedirectToAction("MyDevices");
}
但是在本教程中,它们显示的功能类似:
void ValidateRequestHeader(HttpRequestMessage request)
{
string cookieToken = "";
string formToken = "";
IEnumerable<string> tokenHeaders;
if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
{
string[] tokens = tokenHeaders.First().Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
AntiForgery.Validate(cookieToken, formToken);
}
但是我不知道将这段代码放在控制器中的位置以及如何调用此函数。谁能解释我如何使用以上代码?
它们在本教程的Anti-CSRF和AJAX部分中显示的是一种非标准的令牌验证方法。在此示例中,您将not使用[ValidateAntiForgeryToken]
,而是手动运行验证。首先,您在ajax调用中注入其他头文件:
headers: {
'RequestVerificationToken': '@TokenHeaderValue()'
},
然后从您的操作的标题中读取并验证令牌:
[HttpPost]
public ActionResult Return(DeviceUsage dev)
{
ValidateRequestHeader(Request);
//process action
}
void ValidateRequestHeader(HttpRequestBase request)
{
string cookieToken = "";
string formToken = "";
if (request.Headers["RequestVerificationToken"] != null)
{
string[] tokens = request.Headers["RequestVerificationToken"].Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
AntiForgery.Validate(cookieToken, formToken);
}
[注意,ValidateRequestHeader()
会通过jQuery调用读取之前设置的标头。另外,我对方法进行了一些修改,以接受HttpRequestBase
。
提示:为避免将ValidateRequestHeader()
添加到每个响应ajax调用的控制器,请将其添加到基本控制器(如果有),然后从基本派生所有控制器。甚至更好create您自己的[ValidateAntiForgeryAjaxToken]
属性。
对于那些有这个问题的人公认的答案很好,但正如他提到的那样您应该为清洁代码创建动作过滤器这就是我的方法
创建扩展类和方法
public static class ExtentionUtilty
{
public static string TokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
在cshtml和ajax调用中使用它
$.ajax("api/values", {
type: "post",
contentType: "application/json",
data: { }, // JSON data goes here
dataType: "json",
headers: {
'RequestVerificationToken': '@ExtentionUtilty.TokenHeaderValue()'
}
});
创建ActionFilter
public class ValidateHeaderAntiForgeryAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string cookieToken = "";
string formToken = "";
if (filterContext.HttpContext.Request.Headers["RequestVerificationToken"] != null)
{
string[] tokens = filterContext.HttpContext.Request.Headers["RequestVerificationToken"].Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
try
{
AntiForgery.Validate(cookieToken, formToken);
base.OnActionExecuting(filterContext);
}
catch
{
filterContext.Result = new HttpNotFoundResult();
}
}
}
并像这样简单地使用它:
[HttpPost]
[ValidateHeaderAntiForgery]
[Authorize(Roles = "Admin")]
public ActionResult ActiveBoomSar(int id, modelDto model){}