在ASP.NET MVC中,假如咱們想要將某個頁面(即某個Action)緩存在服務器端,能夠在Action上標上如下特性:web
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這個特性生效,還需如下幾個條件:瀏覽器
一、Action必須是[HttpGet]。緩存
二、Web.Config中設置<system.web>/<compilation debug="false">,即應用程序的編譯條件不能是Debug。服務器
三、頁面響應Response中不能有Cookies。app
ASP.NET MVC 4基於.NET Framework 4或者4.5,因此一樣對Cookies做了判斷,這意味着若是Forms身份驗證的Cookie輸出方式爲HttpOnly,ide
那麼通過驗證的頁面不會輸出頁面緩存,由於每一次響應中都會帶有身份驗證票加密後生成的Cookie。this
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.
大意是說這個方法中處理了服務器端頁面緩存問題,保證每一個未驗證的用戶都需通過驗證,而不是直接讀取服務器端頁面緩存。那麼什麼場景下會出現緩存問題,以及這個緩存問題的具體表現是什麼呢?下面就來演示一下。debug
一、新建ASP.NET MVC 4 Web應用程序,「項目模板」選擇「Internet應用程序」。code
二、自定義一個繼承至"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 }
三、找到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 }
四、通過以上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()就會有問題。