从AntiForgeryToken()获取原始值(不是html)

本文关键字:不是 html 获取 AntiForgeryToken 原始 | 更新日期: 2023-09-27 18:01:36

这个漂亮的抽象允许您将@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的值,但我不应该这样做。是否有其他方法访问/获取这个值?要清楚,我的意思是我想要一个方法的重载,它只返回一个字符串的值,或者某种同时具有名称和值的对象。

为了提供更多的上下文,我的表单和相关的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字符串之前与它进行交互?

从AntiForgeryToken()获取原始值(不是html)

您可以使用这样的代码(例如_Layout.cshtml)向所有Ajax POST请求添加anti伪造头,或者您可以针对特定请求调整它。(代码假定您使用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调用的服务器端,您需要调用antiforged的过载。验证它接受cookie和表单令牌,您可以通过将此属性添加到通过Ajax(显式地,或通过父控制器,或通过过滤器)调用的操作方法来启用
[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);
    }

查看ILSpy中的Html.AntiForgeryToken()并复制构建输入标记的代码,并创建您自己的扩展方法,该方法仅返回令牌字符串。

简短的回答:没有一个本地的方法来做你想做的事情,但是正如前面的回答所说,你可以创建一个HTML助手方法。

这个家伙似乎有一个工作的解决方案:https://stackoverflow.com/a/16057568/724222