zoukankan      html  css  js  c++  java
  • 在ASP.NET MVC 3 中自定义AuthorizeAttribute时需要注意的页面缓存问题

    一、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()就会有问题。

  • 相关阅读:
    火眼金睛算法,教你海量短文本场景下去重
    CynosDB技术详解——架构设计
    CynosDB技术详解——存储集群管理
    解决 "Script Error" 的另类思路
    Go 语言实践(一)
    Vue.js的复用组件开发流程
    MYSQL中的COLLATE是什么?
    Blending
    AlphaTesting
    Culling & Depth Testing
  • 原文地址:https://www.cnblogs.com/bestzrz/p/3073370.html
Copyright © 2011-2022 走看看