6.过滤器
1) 什么是过滤器
1、过滤器(Filters)就是向请求处理管道中注入额外的逻辑。提供了一个简单而优雅的方式来实现横切关注点。
2、所谓的过滤器(Filters),MVC框架里面的过滤器完全不同于ASP.NET平台里面的Request.Filters和Response.Filter对象,它们主要是实现请求和响应流的传输。通常我们所说的过滤器是指MVC框架里面的过滤器。
3、过滤器可以注入一些代码逻辑到请求处理管道中,是基于C#的Attribute的实现。当负责调用Action的类ControllerActionInvoker在调用执行Action的时候会检查Action上面的Attribute并查看这些Attribute是否实现了指定的接口,以便进行额外的代码注入处理。
2) Authorize授权过滤器
Authorize授权过滤器可以在控制器和Action方法使用Authorize特性,在授权过后的用户才可以访问控制器或Action方法。
新建项目,新建AuthorizeController。
在AuthorizeController里面新建两个Action,每个Action添加视图,有一个<h2>标签作为标示。
在AuthorizeAction Action方法上面加上[Authorize]特性。
直接运行程序,地址栏输入/Authorize/index。成功打开页面。
地址栏输入/Authorize/AuthorizeAction。页面提示通过身份验证的用户无权访问处理请求所需的资源。证明了特性[Authorize]起到了作用。
但是这个提示并不友好。权限不足时我们更希望会跳转到一个登陆页面。
在Web.config配置文件<system.web>段内输入代码
<authentication mode="Forms">
<forms loginUrl="~/Authorize/Index" timeout="2880" />
</authentication>
可以把不通过权限认证的用户转到/Authorize/Index页面,timeout指定用户的cookie身份信息存在2880分钟。
运行程序,地址栏输入/Authorize/AuthorizeAction。页面被带到了/Authorize/Index。
先把没有没有验证的用户跳转到 Load action方法进行登陆。
用前一章ef生成模型的方法生成模型用于登陆。
新建get特性的load action,利用基架添加Create的view页面。
基架生成的view页面。
再新建post特性的load action。向数据库查询符合登陆用户名和密码,如果有,就会添加用户名的cookie,维持2880分钟,再跳转到/Authorize/AuthorizeAction页面,表示成功。
运行程序,地址栏输入/Authorize/AuthorizeAction,然后没有权限被带到/Authorize/Load。
输入数据库不存在的name和password,提交,页面不进行跳转。
然后输入数据库有的,提交。
页面成功转到/Authorize/AuthorizeAction,实现了功能。而且cooike存在时间内,/Authorize/AuthorizeAction页面可以直接访问,无须登陆。
下面修改AuthorizeAction view页面。
@User.Identity.Name可以获取当前有登陆权限的用户name。
新建,Lout Action方法,FormsAuthentication.SignOut()删除用户权限。回到登陆页面。
运行程序,地址栏输入/Authorize/AuthorizeAction。因没有权限返回/Authorize/Load,输入正确用户名和密码,登陆。
顺利进入/Authorize/AuthorizeAction页面,点击注销。
回到登陆页面,此时地址栏输入/Authorize/AuthorizeAction。
无法跳转,证明用户权限已被删除。
1) 自定义授权过滤器
如果要自定定义授权过滤器,需要继承AuthorizeAttribute。新建Extensions文件夹,里面新建UserAuthorize类,继承AuthorizeAttribute。
重写OnAuthorization,AuthorizeCore,HandleUnauthorizedRequest方法。
执行OnAuthorization。
22-25行判断是否获得权限认证,没有就转至新的登陆页面。
30-36行查询请求的控制器和方法可以被那些角色访问。然后加入到Roles”角色”里面。
执行AuthorizeCore。
主要获取到当前拥有登陆权限的User,再在初始数据(或数据库)中查询出其角色是否能访问当前的action。返回faslse则转到HandleUnauthorizedRequest。
执行HandleUnauthorizedRequest。
没有授权访问时返回的视图。
所用到的model,放到Models文件夹内。
User:定义用户和角色。
Role:定义角色的名称。
RoleWithControllerAction:定义Controller Action只能由那些角色来访问。
新建DataBase文件夹,里面新建SampleData类用于初始化数据。
在AuthorizeController控制器中新建两个action用于简单登陆。
EasyLoad View。
新建三个action ,Administrators,SeniorMemberJuniorMember。分别用于三种角色的权限访问。每个action 都有自己的view页面作为标示。使用自定义权限特性 [UserAuthorize(AuthorizationFailView = "Error")]。
运行程序,地址栏输入/Authorize/Administrators。在没有登陆用户的情况下页面会跳转到/Authorize/EasyLoad要求登陆。
输入”3”登陆。页面转到/Authorize/AuthorizeAction。
尝试转到/Authorize/Administrators和/Authorize/SeniorMember都提示失败,因为初始数据中用户”3”的角色只能访问/Authorize/JuniorMember。
地址栏输入/Authorize/JuniorMember。成功。
点击注销。在/Authorize/EasyLoad页面登陆用户”1”。
因为初始数据中用户”1”的角色可以访问。/Authorize/Administrators,/Authorize/SeniorMember,/Authorize/JuniorMember。
所以访问这些页面没有转到错误页面。
4) 操作和结果过滤器
操作和结果过滤器用于action执行前,action执行后,action返回前,action返回后的操作。
使用操作和结果过滤器,需要继承ActionFilterAttribute类。在Extensions文件夹下新建ActionFilters类,并继承ActionFilterAttribute。
转到ActionFilterAttribute,可重写四个方法。
OnActionExecuted:在执行操作方法后由 ASP.NET MVC 框架调用。
OnActionExecuting:在执行操作方法之前由 ASP.NET MVC 框架调用。
OnResultExecuted:在执行操作结果后由 ASP.NET MVC 框架调用。
OnResultExecuting:在执行操作结果之前由 ASP.NET MVC 框架调用。
重写了四个方法,在操作和结果过滤器执行时用filterContext.HttpContext.Response.Write(“”)在页面显示一些执行信息。
新建ActionFiltersController控制器,添加Index action。使用自定义的操作和结果过滤器[ActionFilters]。action返回一段<h2>标签。添加View视图输出<h2>作为标示。
运行程序,地址栏输入/ActionFilters/Index。可以看到action和View执行前后都插入了对应的文字,对action操作和返回结果进行控制。
我们可以把操作和结果过滤器ActionFilterAttribute做到自定义权限过滤器AuthorizeAttribute同样的效果。
在文件夹Extensions新建ActionPremisFilters类,继承ActionFilterAttribute。
重写OnActionExecuting Action方法执行前的操作,根据登陆用户判断是否有权限,代码根自定义授权过滤器相似。
新建EasyLoad action方法,[httppost] EasyLoad action方法,用基架Create添加View视图,用于简单登陆。
添加SeniorMember action方法用于测试,使用操作和结果过滤器ActionPremisFilters标示,添加视图作为标示。
DataBase文件夹下SampleData数据初始类中添加新的数据,ActionFilters控制器和SeniorMember 方法只能由角色1,2访问。
运行程序,地址栏输入/ActionFilters/SeniorMember,自动转到ActionFilters/EasyLoad。输入3,登陆。
登陆后转到/ActionFilters/SeniorMember,显示错误。
清除Cookie,再次到/ActionFilters/SeniorMember,用1登陆。成功跳转,因为1在初始数据中,/ActionFilters/SeniorMember能给角色1,2进入,而用户1拥有角色1。
5) 过滤器的顺序
授权过滤器-操作过滤器-结果过滤器-异常过滤器
类上的过滤器优先于方法上的过滤器。
Order属性决定过滤器先后顺序。Order默认为-1。
重写Controller中虚方法优先于方法的过滤器。