Asp.net-Mvc

MVC3 AntiForgeryToken 在 Ajax 登錄時中斷

  • August 22, 2012

ASP.NET MVC 的AntiForgeryToken機制基於目前的HttpContext.User. 當您呼叫Html.AntiForgeryToken(). 基本上沒問題(請參閱此處最後一段中的解釋),但是當您通過Ajax 呼叫登錄時會出現問題。

在我的程式碼中,當使用者登錄時,憑據在 Ajax 中作為 Json 對象發送(AntiForgeryToken隱藏欄位值也在 Json 內部發送),伺服器對使用者進行身份驗證,應用 FormsAuthentication.SetAuthCookie(),並返回一個 Json結果包含一些使用者特定的數據。這樣,我可以避免登錄時刷新整頁。

問題是現在對伺服器的每個後續 Ajax 請求都失敗了ValidateAntiForgeryTokenAttribute,因為它現在需要一個與防偽 cookie 不兼容的防偽令牌。

如何獲取有效的防偽令牌以放入客戶端的隱藏欄位,以便登錄後的每個 Json 請求都會成功?

我試圖手動獲取一個新的隱藏欄位令牌(AntiForgery.GetHtml()在操作中使用,提取令牌字元串本身,將其返回到 Json 中的客戶端並在 JavaScript 中手動將其放置在防偽隱藏欄位中)但它不起作用 -伺服器上的後續 Ajax 呼叫失敗ValidateAntiForgeryTokenAttribute。事實上,每次呼叫AntiForgery.GetHtml()(本質上是Html.AntiForgeryToken()helper 所做的)都會產生一個不同的令牌,這會使前一個令牌無效。

我也嘗試在這裡HttpContext.User = new GenericPrincipal(new GenericIdentity(email), null);設置為詳細,但它不起作用。

注意:由於我的具體情況, 此解決方案對我不起作用: Ajax登錄會更改伺服器上的使用者身份,因此在登錄之前生成的每個令牌都無效;該解決方案也不適用,因為它解決了不同的問題。

您將需要清除並重做登錄時擁有的任何現有表單令牌。這意味著您的登錄程式碼將不得不刷新目前頁面(有點殺死它的 ajax 部分),您自己的令牌實現,或者您需要刷新您的令牌。可以請求部分視圖、提取令牌並更新您的表單。你實際上可以有一個安靜的 url,它只向經過身份驗證的使用者返回一個令牌。有人可能會爭辯說這是一個安全問題,但我不這麼認為,因為它只是一種更簡單的獲取令牌的方法,而不是請求任何視圖 - 部分視圖或其他視圖。

您應該能夠通過以下方式輕鬆獲取要替換的令牌實例:

var token = $('input[name=""__RequestVerificationToken""]');

編輯再讀幾遍後-我質疑

如果使用者沒有登錄,為什麼你會在表單上有一個令牌。你允許在沒有登錄和登錄的情況下“操作”同一個表單?即使在這種情況下,網路上的大多數站點也會重定向登錄。我是否正確理解這一點?如果是這樣,您可能要考慮在此處跳過令牌或為未經身份驗證的使用者使用第二種類型的令牌。我相信您是在說未經身份驗證的使用者已經可以在應用程序中送出某些內容 - 如果我理解正確的話 - 再次送出 - 無需經過身份驗證。

引用自:https://stackoverflow.com/questions/7793203