2017-10-11 67 views
5

我們有一個頁面有幾種形式。每個都有自己的@Html.AntiForgeryToken()。在我的本地機器上,一切都很棒。__RequestVerificationToken並不總是被創建

我們已部署到Azure(PAAS),但__RequestVerificationToken未在每個請求上創建。有時它是在那裏,有時我得到所需的防僞cookie不存在很少我得到的令牌不匹配錯誤

在這一點上,我完全無能爲力。我無法弄清楚我們的代碼或Azure環境中是否有問題?沒有這些形式的Ajax。

我們已將<machineKey>部分添加到我們的web.config。沒有緩存。有時它會在第一次出現在新設備上。

+0

你有沒有找到答案呢? –

+0

不,我們必須取消防僞檢查(它用於簡單的整合表格,沒有關鍵的關鍵)。我們的Azure安裝程序有兩個邏輯CD,因此我猜想它與處理請求和響應的不同CD有關。這只是我的猜測。 – TamerM

+0

我很遺憾聽到這個消息,儘管我不認爲這應該是一個問題,除非你在表單動作中定義了域(然後將用戶重定向到POST的另一張CD,但我懷疑將會是這種情況,因爲如果您使用UrlHelper,那麼不會在域之間重定向用戶)。 –

回答

1

我相信你的問題來自於在一個頁面上有不同的防僞令牌的多種形式。 當請求頁面時,您會在表單隱藏字段中獲取兩個不同的標記,但Cookie中只有一個標記。 表單POST包含導致錯誤的不匹配令牌。

嘗試如果頁面僅包含一種形式,AFT將如何爲您工作。如果它工作正常,那麼我的假設是正確的。

This answer包含多種形式的頁面的可能解決方案,但它具有一些安全缺陷,如here所述。

我不確定爲什麼在本地主機上一切正常。 我創建了一個簡單的應用程序,並嘗試使用正確的cookie標記形式發佈POST,但是之前的會話使用舊的Form標記。令我驚訝的是,這個POST成功通過了。 可能是asp.net在這種情況下對本地請求有一些特殊處理。我沒有在這方面找到任何信息。

如果我的回答還是不幫你請您作進一步的分析提供如下數據:

  1. 原始頁面請求與返回的HTTP標頭和形成防僞標記。
  2. 使用已發送的HTTP標頭形成POST請求。
+0

根據OP的帖子,問題不是令牌不匹配(順便說一句,如果你有多個令牌),也不是總是存在的問題。 此外,ASP.NET在比較之前解密防僞標記。如果您在表單中包含2個不同的標記(如果它們都包含與該Cookie相對應的數據)無關緊要。 此外,我在我自己的系統中看到多個表單和表單標記不是問題,問題是根本沒有瀏覽器發送cookie。 –

+0

確實,令牌不僅僅是作爲二進制緩衝區進行比較,而是通過內置的安全令牌進行解密和比較。關於防僞標記內部的好文章:https://www.codeproject.com/Articles/793384/ASP-NET-Anti-Forgery-Tokens-internals。 OP提到有時他會得到'令牌不符合錯誤',所以我的假設仍然可能是一個問題。如果沒有,那麼我在答案底部所要求的信息應該至少說明它是本地客戶端還是遠程服務器的問題。 – CodeFuller

0

花費的時間和研究的顯著量,使用哨兵和Azure的Web服務器日誌的組合之後,我發現所提到的錯誤的兩個主要的原因:

1)在手機上時,瀏覽器處於後臺,操作系統可能會突然停止釋放資源。發生這種情況時,通常會將頁面存儲在手機的驅動器中,並在瀏覽器重新打開後從該處重新加載。

然而問題是,到目前爲止,作爲會話cookie的防僞令牌已經過期,因爲這基本上是一個新的會話。因此,使用前一個會話中的HTML加載沒有Anti-Forgery Cookie的頁面。這會導致The required anti-forgery cookie is not present異常。

2)儘管看起來相關,但異常通常只與切線相關。原因似乎是在同一時間打開多個選項卡的用戶行爲。

只有當用戶到達帶有窗體的頁面時,纔會分配防僞Cookie。這意味着他們可以訪問您的主頁,並且沒有任何防僞cookie。然後他們可以使用中鍵單擊打開多個選項卡。多個選項卡是多個並行請求,每個請求都沒有防僞cookie。由於這些請求沒有防僞cookie,因此ASP.NET爲其中的每個cookie都生成一個單獨的僞隨機令牌,並在該窗體中使用該令牌;但是,只有收到的最後一個頭的結果纔會被保留。這意味着所有其他頁面在頁面上都會有無效標記,因爲它們的防僞cookie被覆蓋。

對於一個解決方案,我創建了一個全球性的過濾器,應確保

  1. 的防僞cookie被任何頁面上指定的,即使頁面沒有形式,並
  2. 反--Forgery cookie不受會話限制。它的使用期限應調整爲匹配用戶登錄令牌,但應保留在會話之間,以防移動設備在沒有會話的情況下重新加載頁面。

以下代碼是FilterAttribute必須作爲全局過濾器添加到FilterConfig.cs之內。 請注意,雖然我不認爲這會造成安全漏洞,但我絕不是安全專家,因此歡迎任何意見。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class AntiForgeryFilter : FilterAttribute, IActionFilter 
{ 
    public void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var cookie = filterContext.HttpContext.Request.Cookies.Get(AntiForgeryConfig.CookieName); 
     var addCookie = true; 
     if (string.IsNullOrEmpty(cookie?.Value)) 
     { 
      cookie = filterContext.HttpContext.Response.Cookies.Get(AntiForgeryConfig.CookieName); 
      addCookie = false; 
     } 
     if (string.IsNullOrEmpty(cookie?.Value)) 
     { 
      AntiForgery.GetTokens(null, out string cookieToken, out string _); 
      cookie = new HttpCookie(AntiForgeryConfig.CookieName, cookieToken) 
      { 
       HttpOnly = true, 
       Secure = AntiForgeryConfig.RequireSsl 
      }; 
     } 
     cookie.Expires = DateTime.UtcNow.AddYears(1); 
     if(addCookie) filterContext.HttpContext.Response.Cookies.Add(cookie); 
    } 

    public void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
    } 
}