簡體   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