当从jTable到我的MVC5控制器进行CRUD调用时,如何传递AntiForgeryToken?为了完成动作,我必须注释掉看似相当不安全的ValidateAntiForgeryToken部分。如果没有,那么我得到“与服务器通信时出错”。消息。
jTable代码:
$(document).ready(function () {
//Prepare jtable plugin
$('#CandidateTable').jtable({
title: 'Candidates',
actions: {
listAction: '@Url.Action("List")',
deleteAction: '@Url.Action("Delete")',
updateAction: '@Url.Action("Edit")',
createAction: '@Url.Action("Create")'
},
fields: {
ID: {
key: true,
create: false,
edit: false,
list: false
},
FirstName: {
title: '@Html.DisplayNameFor(model => model.FirstName)',
width: '15%'
},
MiddleName: {
title: '@Html.DisplayNameFor(model => model.MiddleName)',
width: '15%'
},
LastName: {
title: '@Html.DisplayNameFor(model => model.LastName)',
width: '15%'
},
AnonymousID: {
title: '@Html.DisplayNameFor(model => model.AnonymousID)',
width: '15%'
},
Email: {
title: '@Html.DisplayNameFor(model => model.Email)',
width: '15%'
},
GUID: {
title: '@Html.DisplayNameFor(model => model.GUID)',
width: '15%',
create: false,
edit: false
}
}
});
//Load person list from server
$('#CandidateTable').jtable('load');
});
ASP.NET MVC 5创建操作:
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Create([Bind(Include = "FirstName,MiddleName,LastName,AnonymousID,Email")] Candidate candidate)
{
try
{
if (ModelState.IsValid)
{
candidate.GUID = System.Guid.NewGuid();
candidate.IsActive = true;
candidate.DateAdded = DateTime.Now.ToUniversalTime();
candidate.DateModified = null;
db.Candidates.Add(candidate);
db.SaveChanges();
return Json(new { Result = "OK", Record = candidate });
}
else
{
throw new Exception("Form is not valid! Please correct it and try again.");
}
}
catch (Exception ex)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
更新:
我明白了。我需要添加一个任意字段( AFT ),然后添加@ HTML.AntiForgeryToken输出的自定义输入。现在我只需要弄清楚如何在Deletes上执行此操作,因为Delete只传递主键(id)
$('#CandidateTable').jtable({
paging: true,
pageSize: 15,
sorting: true,
defaultSorting: 'LastName ASC',
title: 'Candidates',
actions: {
listAction: '@Url.Action("List")',
deleteAction: '@Url.Action("Delete")',
updateAction: '@Url.Action("Edit")',
createAction: '@Url.Action("Create")'
},
fields: {
ID: {
key: true,
create: false,
edit: false,
list: false
},
FirstName: {
title: '@Html.DisplayNameFor(model => model.FirstName)',
width: '15%'
},
MiddleName: {
title: '@Html.DisplayNameFor(model => model.MiddleName)',
width: '15%'
},
LastName: {
title: '@Html.DisplayNameFor(model => model.LastName)',
width: '15%'
},
AnonymousID: {
title: '@Html.DisplayNameFor(model => model.AnonymousID)',
width: '15%'
},
Email: {
title: '@Html.DisplayNameFor(model => model.Email)',
width: '15%'
},
__AFT__: {
create: true,
edit: true,
list: false,
input: function (data) {
return '@Html.AntiForgeryToken()';
}
}
}
答案 0 :(得分:1)
我已经找到了如何添加这个AntiForgeryToken来删除jTable的动作。您已正确添加__AFT__
到创建和更新操作,无需在控制器中添加标头和提取。要将其添加到删除操作,您可以编写自定义删除,如下所示。更新了您的代码
var tokenId = '@Html.AntiForgeryToken()';
$('#CandidateTable').jtable({
paging: true,
pageSize: 15,
sorting: true,
defaultSorting: 'LastName ASC',
title: 'Candidates',
actions: {
listAction: '@Url.Action("List")',
deleteAction: function (postData) {
postData.__RequestVerificationToken = $(tokenId).val();
return $.Deferred(function ($dfd) {
$.ajax({
url: '@Url.Action("Delete")',
type: 'POST',
dataType: 'json',
data: postData,
success: function (data) {
$dfd.resolve(data);
},
error: function () {
$dfd.reject();
}
});
});
},
updateAction: '@Url.Action("Edit")',
createAction: '@Url.Action("Create")'
},
fields: {
ID: {
key: true,
create: false,
edit: false,
list: false
},
FirstName: {
title: '@Html.DisplayNameFor(model => model.FirstName)',
width: '15%'
},
MiddleName: {
title: '@Html.DisplayNameFor(model => model.MiddleName)',
width: '15%'
},
LastName: {
title: '@Html.DisplayNameFor(model => model.LastName)',
width: '15%'
},
AnonymousID: {
title: '@Html.DisplayNameFor(model => model.AnonymousID)',
width: '15%'
},
Email: {
title: '@Html.DisplayNameFor(model => model.Email)',
width: '15%'
},
__AFT__: {
create: true,
edit: true,
list: false,
input: function (data) {
return tokenId;
}
}
}
我自己测试并尝试过这个。希望这会有所帮助。
答案 1 :(得分:0)
要做的第一件事是向View
添加一个会生成防伪令牌的函数:
@functions{
public string TokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
@functions
块允许您向Views
添加功能。它们有助于将所有功能保存在一个有助于组织的位置。
然后,在您的Javascript中,您将进行AJAX调用并将该标记添加为RequestVerificationToken
标题:
$.ajax("api/values", {
type: "post",
contentType: "application/json",
data: { }, // JSON data goes here
dataType: "json",
headers: {
'RequestVerificationToken': '@TokenHeaderValue()' //Can be named whatever
}
});
现在在解决方案中创建以下实用程序方法:
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);
}
并称之为:
try{
Utils.ValidateRequestHeader(request);
}
catch(HttpAntiForgeryException exc){
//VALIDATION FAILED! RELEASE THE HOUNDS
}
参考:http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks
答案 2 :(得分:0)
我有这个代码,也许它会帮助你。我猜jtable使用$ .ajax来处理它的请求,所以我想它应该可以工作。
// Setup CSRF safety for AJAX:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
if (options.type.toUpperCase() === "POST") {
// We need to add the verificationToken to all POSTs
var token = $("input[name^=__RequestVerificationToken]").eq(0);
var headers = {};
headers["__RequestVerificationToken"] = token.val();
if (!token.length) return;
var tokenName = token.attr("name");
// If the data is JSON, then we need to put the token in the QueryString:
if (options.contentType.indexOf('application/json') === 0) {
// Add the token to the URL, because we can't add it to the JSON data:
options.headers = headers;
}
}
});