是否有可能动态地将@Html.AntiForgeryToken()
添加到MVC中的所有表单标记,而不是手动添加到所有页面?
答案 0 :(得分:1)
您可以在母版页上创建另一个表单,以确保创建AntiForgery cookie(如果客户端浏览器中没有它),并且在其关联所需的DOM中存在隐藏字段。
<form id="__AjaxAntiForgeryForm" action="#" method="post">@Html.AntiForgeryToken()</form>
然后使用jQuery或Javascript,您可以拦截所有表单提交,然后添加AntiForgeryToken值,然后访问如下:
$('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val()
有很多方法可以拦截表单提交,我没有时间编写完整的测试,因此您应该在使用之前测试下面的代码,因为它可能有错误。但是您可能希望为应该被拦截或挂钩到其ID的表单定义一个类。但是你的结构可能看起来像这样:
$("#formid").submit(function(e){
e.preventDefault(); //prevent submit
var self = this;
$('<input />').attr('type', 'hidden')
.attr('name', "__RequestVerificationToken")
.attr('value', $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val())
.appendTo('#formid');
self.submit(); }) });
当然,这个解决方案的问题在于客户端需要启用JavaScript,但在今天的日常生活中,这是一个合理的假设。另一种方法是创建自己的自定义HtmlHelper,而不是使用MVC附带的库存标准。但是这种JavaScript方法的另一个好处是可以为您的ajax帖子添加AntiForgery支持,因为您还可以将JavaScript函数添加到同一母版页:
<script type="text/javascript">
AddAntiForgeryToken = function (data) {
data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
return data;
};
</script>
这意味着,为了执行Ajax帖子,您可以执行以下操作:
$.ajax({
url: '/YourTargetUrl',
cache: false,
type: "POST",
data: AddAntiForgeryToken({ field1: value1, ..... fieldx: valuex }),
dataType: "json",
success: function (response) {
},
error: function (xhr, status, error) {
} });
答案 1 :(得分:0)
您可以构建自己的Form HTML帮助程序重载,通过复制FormExtensions源代码中的内容并添加代码以生成防伪标记来自动执行此操作。
public static class FormExtensions
{
public static MvcForm BeginFormWithAntiForgeryToken(this HtmlHelper htmlHelper, string actionName, string controllerName, object routeValues, FormMethod method, object htmlAttributes)
{
return BeginFormWithAntiForgeryToken(htmlHelper, actionName, controllerName, new RouteValueDictionary(routeValues), method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
public static MvcForm BeginFormWithAntiForgeryToken(this HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method, IDictionary<string, object> htmlAttributes)
{
string formAction = UrlHelper.GenerateUrl(null /* routeName */, actionName, controllerName, routeValues, htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, true /* includeImplicitMvcValues */);
return FormHelper(htmlHelper, formAction, method, htmlAttributes);
}
// TODO: Add additional overloads
private static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{
TagBuilder tagBuilder = new TagBuilder("form");
tagBuilder.MergeAttributes(htmlAttributes);
// action is implicitly generated, so htmlAttributes take precedence.
tagBuilder.MergeAttribute("action", formAction);
// method is an explicit parameter, so it takes precedence over the htmlAttributes.
tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);
bool traditionalJavascriptEnabled = htmlHelper.ViewContext.ClientValidationEnabled
&& !htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled;
if (traditionalJavascriptEnabled)
{
// forms must have an ID for client validation
tagBuilder.GenerateId(htmlHelper.ViewContext.FormIdGenerator());
}
htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
// THIS WAS ADDED: Write the anti-forgery token
htmlHelper.ViewContext.Writer.Write(System.Web.Helpers.AntiForgery.GetHtml().ToString());
MvcForm theForm = new MvcForm(htmlHelper.ViewContext);
if (traditionalJavascriptEnabled)
{
htmlHelper.ViewContext.FormContext.FormId = tagBuilder.Attributes["id"];
}
return theForm;
}
}
然后,您只需在创建表单时调用HTML帮助程序。
@Html.BeginFormWithAntiForgeryToken("Edit", "User", new { id = 123 }, FormMethod.Post, null) {
<!-- Add form elements here -->
}