花費的時間和研究的顯著量,使用哨兵和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被覆蓋。
對於一個解決方案,我創建了一個全球性的過濾器,應確保
- 的防僞cookie被任何頁面上指定的,即使頁面沒有形式,並
- 反--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)
{
}
}
你有沒有找到答案呢? –
不,我們必須取消防僞檢查(它用於簡單的整合表格,沒有關鍵的關鍵)。我們的Azure安裝程序有兩個邏輯CD,因此我猜想它與處理請求和響應的不同CD有關。這只是我的猜測。 – TamerM
我很遺憾聽到這個消息,儘管我不認爲這應該是一個問題,除非你在表單動作中定義了域(然後將用戶重定向到POST的另一張CD,但我懷疑將會是這種情況,因爲如果您使用UrlHelper,那麼不會在域之間重定向用戶)。 –