在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()就会有问题。
在ASP.NET MVC 3 中自定义AuthorizeAttribute时需要注意的页面缓存问题的更多相关文章
- [转]在 ASP.NET MVC 4 中创建为移动设备优化的视图
原文链接 https://msdn.microsoft.com/zh-cn/magazine/dn296507.aspx 如果深入探讨有关编写移动设备网站的常识性考虑因素,会发现其中有一种内在矛盾. ...
- ASP.NET MVC 4中如何为不同的浏览器自适应布局和视图
在ASP.NET MVC 4中,可以很简单地实现针对不同的浏览器自适应布局和视图.这个得归功于MVC中的"约定甚于配置"的设计理念. 默认的自适应 MVC 4自动地为移动设备浏览器 ...
- 在ASP.NET MVC环境中使用加密与解密
在.NET Framework 4.5的NET框架中,在程序中加密与解密很方便.现在均学习ASP.NET MVC程序了,因此Insus.NET也在此写个学习的例子.在需要时可以参考与查阅. 写一个Ut ...
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证,在默认的情况下,基于ValidationAttribute的声明是验证被使用,我们只需 要将相应的ValidationAttr ...
- 在 ASP.NET MVC 项目中使用 WebForm、 HTML
原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各 ...
- asp.net mvc Route 使用自定义条件(constraints)禁止某ip登陆
asp.net mvc Route 使用自定义条件(constraints)禁止某ip登陆 前言 本文的目的是利用Mvc route创建一个自定义约束来控制路由跳转实现禁止ip登陆,当然例子可能不合理 ...
- C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(中)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(中)),不对的地方欢迎指出与交流. 章节出自<Professional C# ...
- 在ASP.NET MVC应用中开发插件框架(中英对照)
[原文] Developing a plugin framework in ASP.NET MVC with medium trust [译文] 在ASP.NET MVC应用中开发一个插件框架 I’v ...
- 【初学者指南】在ASP.NET MVC 5中创建GridView
介绍 在这篇文章中,我们将会学习如何在 ASP.NET MVC 中创建一个 gridview,就像 ASP.NET Web 表单中的 gridview 一样.服务器端和客户端有许多可用的第三方库,这些 ...
随机推荐
- ubuntu开启ftp服务
首先再防火墙中开启21和20端口 iptables -A INPUT -p tcp --dport -j ACCEPT iptables -A INPUT -p tcp --dport -j ACCE ...
- Linux环境下的make和makefile详解
无论是在Linux还是在Unix环境中,make都是一个非常重要的编译命令.不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或make install.利用make工具,我们可以将大型 ...
- Python 字符串与数字拼接报错
Python 不像 JS 或者 PHP 这种弱类型语言里在字符串连接时会自动转换类型,而是直接报错. 如: 上述是Python 字符串与数字拼接报错,解决办法是:使用bytes函数把int型转换为st ...
- 【DataStructure】Some useful methods about linkedList.
/** * Method 1: Delete the input element x * and meanwhile keep the length of array after deleted n ...
- pcie dma的玩法
There is some issue with the implement script. So I took the manual steps. 1. Created the pcie core ...
- AppModify修改app.config
public class AppModify { /// <summary> /// 依据连接串名字connectionName返回数据连接字符串 /// </summary> ...
- android:Notification实现状态栏的通知
在使用手机时,当有未接来电或者新短消息时,手机会给出响应的提示信息,这些提示信息一般会显示到手机屏幕的状态栏上. Android也提供了用于处理这些信息的类,它们是Notification和Notif ...
- boost 库的安装
一.windows下 环境:win7 64位 方法1:使用.exe类型的boost进行安装,也就是编译过得,这种方法最简单.下载后直接执行.exe就行了. http://sourceforge.net ...
- Oracle 11g安装图文攻略
一.Oracle 下载 注意Oracle分成两个文件,下载完后,将两个文件解压到同一目录下即可. 路径名称中,最好不要出现中文,也不要出现空格等不规则字符. 官方下地址: http://www.ora ...
- MUTT+MSMTP利用163服务器发送邮件
监控系统发送告警邮件,我们自己搭建邮件服务器,成本较高,所以可以使用163等第三方MTA帮助我们发送.MUTT+MSMTP是一个很好的选择,具体实现如下: tar -xvf msmtp-1.6.5.t ...