在ASP.NET MVC 3 中自訂AuthorizeAttribute時需要注意的頁面緩衝問題

來源:互聯網
上載者:User
一、ASP.NET MVC中使用OutputCache實現伺服器端頁面級緩衝

    在ASP.NET MVC中,假如我們想要將某個頁面(即某個Action)緩衝在伺服器端,可以在Action上標上以下特性:

1 [OutputCache(Duration = 10, VaryByParam = "*", Location = OutputCacheLocation.Server)] 2 public ActionResult Login() 3 { 4     ViewBag.Message = "Your app description page. " + DateTime.Now.ToString(); 5     LoginModel loginModel = new LoginModel(); 6     ViewBag.IsValCodeVisible = IsValCodeVisible(); 7     return View(new LoginModel()); 8 } 

    想要使OutputCache這個特性生效,還需以下幾個條件:

1、Action必須是[HttpGet]。

2、Web.Config中設定<system.web>/<compilation debug="false">,即應用程式的編譯條件不能是Debug。

3、頁面響應Response中不能有Cookies。

  • 1)在.NET Framework 2.0.50727.4209以前,包含Cookies的頁面響應可以輸出緩衝,源碼如下:

 

  • 2)從.NET Framework 2.0.50727.4209開始,加入了對Cookies的判斷,如果頁面響應中包含Cookies,則不輸出緩衝,而是重新執行代碼。

    ASP.NET MVC 4基於.NET Framework 4或者4.5,所以同樣對Cookies作了判斷,這意味著如果Forms身分識別驗證的Cookie輸出方式為HttpOnly,

那麼經過驗證的頁面不會輸出頁面緩衝,因為每一次響應中都會帶有身分識別驗證票加密後產生的Cookie。

二、為什麼說盡量不要重寫AuthorizeAttribute的OnAuthorization()方法?

    AuthorizeAttribute的源碼中的OnAuthorization()方法有這樣的注釋:

// Since we're performing authorization at the action level, the //authorization code runs // after the output caching module. In the worst case this could allow //an authorized user // to cause the page to be cached, then an unauthorized user would //later be served the // cached page. We work around this by telling proxies not to cache the //sensitive page, // then we hook our custom authorization code into the caching //mechanism so that we have // the final say on whether a page should be served from the cache. 

    大意是說這個方法中處理了伺服器端頁面緩衝問題,保證每個未驗證的使用者都需經過驗證,而不是直接讀取伺服器端頁面緩衝。那麼什麼情境下會出現緩衝問題,以及這個緩衝問題的具體表現是什麼呢?下面就來示範一下。

1、建立ASP.NET MVC 4 Web應用程式,“項目模板”選擇“Internet應用程式”。

2、自訂一個繼承至"AuthorizeAtrribute"的類,這個類重寫了OnAuthorization(),並且沒有針對OutputCache進行處理。

 1 public class CustomAuthorizeAttribute : AuthorizeAttribute  2 {  3     public override void OnAuthorization(AuthorizationContext filterContext)  4     {  5         if (!filterContext.HttpContext.User.Identity.IsAuthenticated)  6         {  7             HandleUnauthorizedRequest(filterContext);  8         }  9     } 10 } 

 

3、找到Controllers/HomeController/Index,標註以下特性。

1 [HttpGet] 2 [CustomAuthorize] 3 [OutputCache(Duration = 30, Location = OutputCacheLocation.Server, VaryByParam = "*")] 4 public ActionResult Index() 5 { 6     ViewBag.Message = "修改此模板以快速啟動你的 ASP.NET MVC 應用程式。"; 7     return View(); 8 } 

 

4、經過以上3個步驟後,按照預期,一個使用者訪問完Home/Index後,Home/Index這個頁面會在伺服器端緩衝起來(Location = OutputCacheLocation.Server),後續的另一個使用者訪問Home/Index,則會直接讀取頁面緩衝,而不需要重新執行Home/Index的代碼(當然也包括身分識別驗證等特性的代碼)。為了類比兩個不同的使用者,下面選擇Chrome和IE兩個不同的瀏覽器訪問頁面。

   首先開啟Chrome瀏覽器,訪問Account/Login,輸入帳號密碼進行登入,然後訪問首頁Home/Index,顯示如下:

 

   

    接著開啟IE瀏覽器,直接存取Home/Index。如果沒有頁面緩衝,這時候是不能直接開啟頁面的,因為Home/Index已經標註了[CustomAuthorize],是需要身分識別驗證的,但因為有了頁面緩衝,所以伺服器直接將第一次在Chrome瀏覽器訪問Home/Index時在伺服器留下的緩衝發送給IE瀏覽器的請求。頁面顯示如下:

 

   

ASP.NET儲存Cookie的方式預設不是HttpOnly,不會在每次頁面響應中帶有Cookie,伺服器端的OutputCache可以生效,所以這種情況下重寫AuthorizeAttribute的OnAuthorization()就會有問題。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.