第9讲 使用Filter特性
2010.9.9 苏鹏
内容介绍
-基本Filter的使用
-自定义开发Filter
预备知识
-安装Visual Studio 2010 Express
-了解ASP.Net
-了解设计模式基本概念
Filter的作用
-对Action的附加说明
ASP.Net MVC中的Filter
-Authorize
ASP.Net里面也有授权管理,它是用Membership来做的,绑定每个文件的Url。这里MVC的授权是在Action访问之前要求用户名和密码,证明您是具有相应操作权限的
-HandleError
Action中会抛出异常,HandleError加上之后就能处理这个异常
-OutputCache
缓存输出的内容
-RequireHttps
这也是授权,但是要求更严格,网络上传输的请求很多都是Http,即超文本传输协议,它传输的文本是明文的,它顶多做点Encode是把一些字符转义一下,不会对数据进行加密,这样是很不安全的。现在网络的Sniffer技术已经很流行了,任何人只要在网桥上架一个监听器,都能听到你相应的流量。如果对流量进行分析,就能看到流量里的内容。所以对于一些高安全性要求的网络,例如网络银行等,都是用Https进行传输,s的意思是传输在SSL层上,SSL层是传输的一个加密协议,它保证传输过程当中,双方使用一种保密机制来进行传输,而不会被第三方监听到,即使监听到也分析不明白,全部是乱码。所以Https有效地避免了传输数据被监听的情况。RequireHttps标签,它就会要求你,一旦使用这个标签,数据传输一定必须得是Https进行的。如果是Http的,那就会有一些处理策略。
Authorize
-AuthorizeAttribute标签
在ASP.Net 2.0时代,我们为了让用户使用角色和权限管理,微软提供了一套针对用户角色和权限管理的架构,即Membership。这个核心部分有几部分,第一部分有一大堆Membership对应的控件,这些控件能帮助您创建用户、登录、显示用户登录状态等等。第二部分有一堆Service的API,隶属于Membership命名空间下,它能创建用户、查看用户是否登录、验证用户是否属于某一权限。最底层,它有一个数据库,里面有5个表,其中有角色Roles(每一不同角色针对不同文件夹访问)、用户Users(每个Users隶属于一个角色,Users有登录信息),这5个表保存了权限管理的数据。这个Service依然在今天MVC架构中可以使用。这就是今天的AuthorizeAttribute标签。标签中的Roles就是验证登陆的角色名,这个例子表名只有角色名叫Admins和SuperAdmins的用户可以访问。如果是用户名验证,可以写Users="XXX,XXX"(用逗号分隔)。只有指定的名称的属性才能访问到。
这和以前ASP.Net WebForm的Membership用法有所不同。假如有一些页面是只有Admin用户能操作的,那我们就创建一个叫Admin的文件夹,接下来把用户操作文件全部放到Admin文件夹下面。用户想要访问这些文件的时候,就必须要通过权限认定。对每一文件夹的定义Rules写在Webconfig里边。
MVC架构下就无法复用这种策略,为什么呢?想想MVC架构的基础概念。每一个请求现在对应的已经不再是
一个文件了,它对应的是个Action。这就使得我们指定一个文件夹下的文件的方式不合适了。所以针对不同用户,我们要限制和管理的只不过是他们的一个操作。这个操作最小粒度就是一个函数,即Action。这样把权限和用户操作挂钩,而不是文件,反而更有效。
上面的例子中,如果要使用DeleteAllUsers方法,必须首先具有Admins或SuoerAdmins的角色,通过AdminController的权限,然后还需要是名叫Phil的用户,才能访问这个Action。这个逻辑关系实际上是一种叠加的逻辑关系。
如果只写了Authorize的标签,没有写后面的条件,那就说明这只是登录授权,只要用户登录就可以访问Action。如果是没登陆想访问带有Authorize标签的方法,会返回一个401错误,它在IIS里面的意思就是您所访问的资源未经授权。当然,同ASP.Net WebForm一样,MVC架构中这种未授权的情况也可以让用户跳转到一个登陆页面。
RequireHttps
这个标签要求请求必须是Https。它既可以放在Controller上,也可以放在Action上。RequireHttps标签的Action被访问的时候,要求必须使用SSL来进行解析,如果有一个不是使用SSL的请求发过来的时候,就要分情况讨论了,如果是Get请求,那么我们自动会把协议变成Https的,然后接着访问。但要注意,您的Web服务器还必须得支持Https,如果它把协议变成了Https,但是您的服务器不支持Https,那一样是报告404错误的。如果是Post请求,那么是没法加密Post里面的信息的,因此会抛出异常。
OutputCache
-CacheProfile
指定Cache名字,这个名字可以写在Filter上,也可以写在Web.config上。写在Web.config上就可以复用OutputCache的规则
-Duration
指定缓存释放时间,单位秒
-Location
默认情况是Any
-NoStore
表示不缓存结果
-SqlDependency
指定缓存是根据某一SQL Server指定的某一表的值来缓存的,当值改变的时候缓存释放,当值没变的时候一直缓存
-VaryByContentEncoding
它是用一个逗号分隔的字符串说明缓存所用的编码格式
-VaryByCustom
是否缓存取决于调用GetValueByCustomString这个函数。这个函数是在Global.asax.cs里的,你在这里重载它的GetValueByCustomString函数,就能自己定制缓存
-VaryHeader
它是取决于Http请求的信息做缓存释放,你可以使用不同的方式来请求同一个Action来实现缓存的释放
-VaryByParam
根据参数释放缓存
在Action上写OutputCache标记之后,当请求发到Controller,Controller执行ActionInvoker找到Action的时候,说:你,准备起来干活了!Action说我不用干啊,你看我这有OutputCache标记呢,释放时间还没到呢,你去View层直接把缓存结果放回去就完事。这样就避免了性能的额外开销。
OutputCache在Web.config里面的配置
Exception Filter
它是指定一个Action去处理你的异常,并且指定一个View视图来指定显示你的异常。
如果是没有Handle异常,那么就不能正确的通过视图返回结果给用户,就会发生很多奇怪的事情,例如一运行就会报错,而错误出处和信息都不知道。
需要注意的是,异常捕获的定义需要从小到大地写,你要细分地每一个都写出来。它们的调用顺序是Order1先调用,Order2后调用。如果不写Order调用的顺序是未知的,不是谁写在上面谁先调用。应该尽量把大的异常的Order写的靠后。
在默认Debug运行下Filter不会捕获这个异常。因为Debug模式如果有异常直接抛给编译器了,这个标签就不起作用。
Custom Filters
要写自定义Filter,首先要继承自FilterAttribute类,然后要实现上面4个接口中的一个。其中ActionFilter和ResultFilter最常用,一个是专门在Action执行前执行中做操作的,一个是执行后返回前做操作的。
ActionFilterAttribute
ActionExecutingContext
它有两个参数:
-ActionParameters
它是一个字典类,它主要用来传递给Action的参数
-Result
在当前请求被取消的时候,Filter会自己生成一个ActionResult来代替从Action传过来的结果,把它传给用户
ActionExecutedContext
它有四个属性:
-Canceled
它是布尔值,如果设为True,Action请求就被取消,直接就会构造一个Result,给ActionExecutedContext里的Result,直接返回。
-Exception
它是抛出异常的支持情况
-ExceptionHandled
它是一个布尔值,可以把它设为True来撤销已经返回的Result。一旦它设为True,抛出异常,所有的Action都拿不到这个ActionResult结果,这个Result就永远丢失了
-Result
Action的返回结果
ResultExecutingContext
-Cancel
-Result
ResultExecutedContext
-Canceled
-Exception
-ExceptionHandled
-Result
编写ActionFilter
这里StopWatch之所以用ViewData存放而不是用全局的变量存放,是因为全局变量会对性能有一定影响。还不如把数据交给Action,因为反正Controller都会把数据给Action。
Filter执行顺序
-1.Order小的先执行
-2.具有同样Order的,看定义范围
-3.无Order的最后执行
-4.代码内部定义的(自己定义的Filter)优先执行
-5.同类型的Filter无法确定执行顺序
总结
-基本Filter的使用
-自定义开发Filter
2010.10.2