繁体   English   中英

在ASP.Net MVC中使用@ Html.AntiForgeryToken()提供CSRF令牌的替代方法

[英]Alternative way to provide CSRF Token instead using @Html.AntiForgeryToken() in ASP.Net MVC

我正在使用ASP.Net MVC后端处理一个有angular 2应用程序。 为此, index.cshtml包含了@Html.AntiForgeryToken(); 所以我得到一个隐藏的输入元素,其中Token作为其值。 在我的前端,我可以抓住这个令牌并将其用于我的请求。 到现在为止还挺好。

现在,由于用户信息用于在后端生成令牌,我必须在某些场合切换令牌。 这个问题在这里描述了问题

现在因为我不想在我的应用程序中进行整页重新加载,我必须使用一种解决方法。 为此,我在后端创建了一个局部视图,它只是使用@Html.AntiForgeryToken();此输入@Html.AntiForgeryToken(); 使用像这样的简单方法作为ActionResult

public ActionResult GetAntiForgery()
{
    return PartialView("~/Views/Home/AntiForgery.cshtml");
}

登录/注销后,我从我的前端调用此函数并替换我现有的AntiForgery input element的值,如下所示:

getAntiForgery(url:string) {
        return this._http.get(url)
            .map((response:any) => {
                let originalXsrfElement = <HTMLInputElement>document.querySelector('[name=__RequestVerificationToken]');
                let body = response._body;

                if(body) {
                    let helperElem = document.createElement('div');
                    helperElem.innerHTML = body;
                    let helperInputElem = <HTMLInputElement>helperElem.firstChild;
                    originalXsrfElement.value = helperInputElem.value;
                }

                return response;
            });
    }

我甚至不能告诉你最让我烦恼的是什么。 我讨厌提出一个额外的请求(但不要在这里深入讨论)但对我来说更糟糕的是我必须要求一些东西,得到一个html字符串并且必须从中提取令牌字符串。

如果我是后端人,我会杀死前端人(我..)甚至考虑创建一个额外的局部视图,创建一个额外的方法,并始终在登录/注销而不是一个请求。

有没有更好的办法? 例如,我想调用一个方法,该方法只使用正确的令牌而不是HTML snippet发出JSON 更好的是,在后端的现有JsonResult方法中,我想将新的CSRF Token添加为属性。

我不是一个后端架构师,所以一般来说我可能会有一些错误,但我的后端同事不介意我在那里做什么所以它不应该那么遥远。

任何提示都表示赞赏。

您可以在操作中使用AntiForgery.GetToken在返回的JSON上设置一些属性:

string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
json.RequestVerificationToken = cookieToken + ":" + formToken;

然后,将其传递回下一个AJAX请求的标头:

$.ajax("/my/awesome/url", {
    type: "post",
    contentType: "application/json",
    data: { ... },
    dataType: "json",
    headers: {
        'RequestVerificationToken': requestVerificationToken
    }
});

由于它不再由cookie处理,因此您不能只使用标准的ValidateAntiForgeryToken属性。 您需要手动检查标头并验证它。 但是,您应该能够创建可以使用的自定义属性:

AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateAntiForgeryTokenFromHeaderAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.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);
    }
}

然后,只需使用[ValidateAntiForgeryTokenFromHeader]装饰您的操作。

[改编自http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks的代码]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM