从 AntiForgeryToken() 获取原始值(不是 html)
Get the raw values (not html) from AntiForgeryToken()
这个美丽的抽象让您可以将 @Html.AntiForgeryToken()
放入 cshtml 文件中,该文件神奇地扩展为类似的东西;
<input name="__RequestVerificationToken" type="hidden" value="JjMHm5KJQ/qJsyC4sgifQWWX/WmADmNvEgHZXXuB07bWoL84DrmQzE6k9irVyFSJ5VSYqeUIXgl4Dw4NHSotLwflGYTyECzLvrgzbtonxJ9m3GVPgUV7Z6s2Ih/klUB78GN7Fl4Gj7kxg62MEoGcZw175eVwTmkKJ0XrtEfD5KCVvYIMHNY8MT2l+qhltsGL87c9dII42AVoUUQ2gTvfPg==" />
在提供页面之前通过 mvc。但是,我的页面有一些 JavaScript 进行 ajax 调用,这些调用不包含令牌,即使它已添加到表单中也是如此。他们目前正在获得预期的 [HttpAntiForgeryException]: A required anti-forgery token was not supplied or was invalid.
,因为他们没有令牌。我知道我 可以 解析 DOM 中的值,但我不应该这样做。 accessing/getting 这个值还有其他方法吗?明确地说,我的意思是我想要 returns 的方法重载,只是将值作为字符串或某种同时具有名称和值的对象。
为了提供更多上下文,我的表单和相关的 JS 看起来有点像这样;
<form action="/settings" method="post"><input name="__RequestVerificationToken" type="hidden" value="JjMHm5KJQ/qJsyC4sgifQWWX/WmADmNvEgHZXXuB07bWoL84DrmQzE6k9irVyFSJ5VSYqeUIXgl4Dw4NHSotLwflGYTyECzLvrgzbtonxJ9m3GVPgUV7Z6s2Ih/klUB78GN7Fl4Gj7kxg62MEoGcZw175eVwTmkKJ0XrtEfD5KCVvYIMHNY8MT2l+qhltsGL87c9dII42AVoUUQ2gTvfPg==" /> <fieldset>
<h3>User Settings</h3>
<ul>
<li>
label for="password">Password</label>
<a href="#" id="change_password" class="changePasswordButton">Edit</a>
<div id="password_section" class="inlineedit">
<div>
<span for="existing_password">Current password</span> <input autocomplete="off" class="required" id="existing_password" name="existing_password" type="password" />
</div>
<div>
<span for="new_password">New password</span> <input autocomplete="off" class="required" id="new_password" name="new_password" type="password" />
<span id="password_strength" />
</div>
<div>
<span for="confirm_password">Confirm password</span> <input autocomplete="off" class="required" id="confirm_password" name="confirm_password" type="password" />
</div>
<div class="inlinesave">
<input type="button" value="Change" onclick="onPostChangePassword();"/>
<a href="#" id="cancel_password" class="cancel">Cancel</a>
</div>
</div>
</li>
// a bunch more of these that call their own onPostChangeSetting method
onPostChangePassword()
然后进行一些输入验证;
if(validPWD && validNewPWD && validConfirmPWD && current_pwd != new_pwd){
// Post the password change
var currentAjaxRequest = $.ajax({
type: "POST",
url: "/settings/preferences/changepassword",
cache: false,
data: {password: $('#new_password').val(), current: $('#existing_password').val(),confirm: $('#confirm_password').val()},
success: password_success,
error: password_error,
dataType: "json"
});
return true;
}
理想情况下(因为这是在 cshtml 文件中逐字记录的)应该用这样的东西进行修改;
data: {password: $('#new_password').val(), current: $('#existing_password').val(),confirm: $('#confirm_password').val(),
__RequestVerificationToken:@Html.AntiForgeryValue() }
tl;dr 有没有办法在 AntiForgeyToken 变成 html 的字符串之前与它交互?
查看 ILSpy 中的 Html.AntiForgeryToken() 并复制构建输入标签的代码并创建您自己的 returns 仅令牌字符串的扩展方法。
您可以使用这样的代码(例如 _Layout.cshtml)将 AntiForgery header 添加到所有 Ajax POST 请求,或者您可以调整它以用于具体要求。 (代码假定您使用的是 jQuery)
@functions{
private static string TokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
<script type="text/javascript">
$(document).ajaxSend(function (event, jqxhr, settings) {
if (settings.type == "POST") {
jqxhr.setRequestHeader('@ValidateHttpAntiForgeryTokenAttribute.RequestVerificationTokenName',
'@TokenHeaderValue()');
}
});
</script>
在这些 Ajax 调用的服务器端,您随后想要调用 the overload of AntiForgery.Validate that takes the cookie and form token,您可以通过将此属性添加到通过 Ajax 调用的操作方法来启用它(明确,或通过 parent 控制器,或通过过滤器)
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
AllowMultiple = false, Inherited = true)]
public sealed class ValidateHttpAntiForgeryTokenAttribute
: FilterAttribute, IAuthorizationFilter
{
public const string RequestVerificationTokenName = "RequestVerificationToken";
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
ValidateRequestHeader(filterContext.HttpContext.Request);
}
else
{
AntiForgery.Validate();
}
}
private static void ValidateRequestHeader(HttpRequestBase request)
{
string cookieToken = string.Empty;
string formToken = string.Empty;
var tokenValue = request.Headers[RequestVerificationTokenName];
if (string.IsNullOrEmpty(tokenValue) == false)
{
string[] tokens = tokenValue.Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
AntiForgery.Validate(cookieToken, formToken);
}
简短回答:没有一种本机方法可以执行您正在尝试做的事情,但正如之前的回答所述,您可以创建一个 HTML 辅助方法。
这家伙似乎有一个可行的解决方案:
这个美丽的抽象让您可以将 @Html.AntiForgeryToken()
放入 cshtml 文件中,该文件神奇地扩展为类似的东西;
<input name="__RequestVerificationToken" type="hidden" value="JjMHm5KJQ/qJsyC4sgifQWWX/WmADmNvEgHZXXuB07bWoL84DrmQzE6k9irVyFSJ5VSYqeUIXgl4Dw4NHSotLwflGYTyECzLvrgzbtonxJ9m3GVPgUV7Z6s2Ih/klUB78GN7Fl4Gj7kxg62MEoGcZw175eVwTmkKJ0XrtEfD5KCVvYIMHNY8MT2l+qhltsGL87c9dII42AVoUUQ2gTvfPg==" />
在提供页面之前通过 mvc。但是,我的页面有一些 JavaScript 进行 ajax 调用,这些调用不包含令牌,即使它已添加到表单中也是如此。他们目前正在获得预期的 [HttpAntiForgeryException]: A required anti-forgery token was not supplied or was invalid.
,因为他们没有令牌。我知道我 可以 解析 DOM 中的值,但我不应该这样做。 accessing/getting 这个值还有其他方法吗?明确地说,我的意思是我想要 returns 的方法重载,只是将值作为字符串或某种同时具有名称和值的对象。
为了提供更多上下文,我的表单和相关的 JS 看起来有点像这样;
<form action="/settings" method="post"><input name="__RequestVerificationToken" type="hidden" value="JjMHm5KJQ/qJsyC4sgifQWWX/WmADmNvEgHZXXuB07bWoL84DrmQzE6k9irVyFSJ5VSYqeUIXgl4Dw4NHSotLwflGYTyECzLvrgzbtonxJ9m3GVPgUV7Z6s2Ih/klUB78GN7Fl4Gj7kxg62MEoGcZw175eVwTmkKJ0XrtEfD5KCVvYIMHNY8MT2l+qhltsGL87c9dII42AVoUUQ2gTvfPg==" /> <fieldset>
<h3>User Settings</h3>
<ul>
<li>
label for="password">Password</label>
<a href="#" id="change_password" class="changePasswordButton">Edit</a>
<div id="password_section" class="inlineedit">
<div>
<span for="existing_password">Current password</span> <input autocomplete="off" class="required" id="existing_password" name="existing_password" type="password" />
</div>
<div>
<span for="new_password">New password</span> <input autocomplete="off" class="required" id="new_password" name="new_password" type="password" />
<span id="password_strength" />
</div>
<div>
<span for="confirm_password">Confirm password</span> <input autocomplete="off" class="required" id="confirm_password" name="confirm_password" type="password" />
</div>
<div class="inlinesave">
<input type="button" value="Change" onclick="onPostChangePassword();"/>
<a href="#" id="cancel_password" class="cancel">Cancel</a>
</div>
</div>
</li>
// a bunch more of these that call their own onPostChangeSetting method
onPostChangePassword()
然后进行一些输入验证;
if(validPWD && validNewPWD && validConfirmPWD && current_pwd != new_pwd){
// Post the password change
var currentAjaxRequest = $.ajax({
type: "POST",
url: "/settings/preferences/changepassword",
cache: false,
data: {password: $('#new_password').val(), current: $('#existing_password').val(),confirm: $('#confirm_password').val()},
success: password_success,
error: password_error,
dataType: "json"
});
return true;
}
理想情况下(因为这是在 cshtml 文件中逐字记录的)应该用这样的东西进行修改;
data: {password: $('#new_password').val(), current: $('#existing_password').val(),confirm: $('#confirm_password').val(),
__RequestVerificationToken:@Html.AntiForgeryValue() }
tl;dr 有没有办法在 AntiForgeyToken 变成 html 的字符串之前与它交互?
查看 ILSpy 中的 Html.AntiForgeryToken() 并复制构建输入标签的代码并创建您自己的 returns 仅令牌字符串的扩展方法。
您可以使用这样的代码(例如 _Layout.cshtml)将 AntiForgery header 添加到所有 Ajax POST 请求,或者您可以调整它以用于具体要求。 (代码假定您使用的是 jQuery)
@functions{
private static string TokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
<script type="text/javascript">
$(document).ajaxSend(function (event, jqxhr, settings) {
if (settings.type == "POST") {
jqxhr.setRequestHeader('@ValidateHttpAntiForgeryTokenAttribute.RequestVerificationTokenName',
'@TokenHeaderValue()');
}
});
</script>
在这些 Ajax 调用的服务器端,您随后想要调用 the overload of AntiForgery.Validate that takes the cookie and form token,您可以通过将此属性添加到通过 Ajax 调用的操作方法来启用它(明确,或通过 parent 控制器,或通过过滤器)
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
AllowMultiple = false, Inherited = true)]
public sealed class ValidateHttpAntiForgeryTokenAttribute
: FilterAttribute, IAuthorizationFilter
{
public const string RequestVerificationTokenName = "RequestVerificationToken";
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
ValidateRequestHeader(filterContext.HttpContext.Request);
}
else
{
AntiForgery.Validate();
}
}
private static void ValidateRequestHeader(HttpRequestBase request)
{
string cookieToken = string.Empty;
string formToken = string.Empty;
var tokenValue = request.Headers[RequestVerificationTokenName];
if (string.IsNullOrEmpty(tokenValue) == false)
{
string[] tokens = tokenValue.Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
AntiForgery.Validate(cookieToken, formToken);
}
简短回答:没有一种本机方法可以执行您正在尝试做的事情,但正如之前的回答所述,您可以创建一个 HTML 辅助方法。
这家伙似乎有一个可行的解决方案: