第11章 过滤器
11.1身份认证和授权
11.1.1 ASP.NET MVC的身份认证方式
表11-1 身份验证的类型 | |
身份验证类型 | 说明 |
Windows | 提供了一种能够使用Window操作系统平台和NTFS文件系统安全性的方法。该验证安全性比较高,但只能用Window平台,并且要求访问者在Web服务器所在的域中拥有一个用户账号。所以该验证仅适合某些公司内部站点使用,不适用于面向大众的商业站点。 |
Forms | 为验证请求将被重定向到一个特定的网页,该网页会从用户哪里获得凭证,并把凭证提交给应用程序用于身份验证。 |
Passport | Microsoft提供的一种单点登录方式,单点登录就是一种跨域、跨站点的登录验证方式。使用该验证方式需要付费,并且注册通行证服务。 |
Federated | Google提供的一种联合身份验证标准,使用该认证方式可以实现让用户使用同样的标识数据访问多个系统。 |
None | 无验证,允许匿名访问,或手动编码控制用户访问。 |
ASP.NET MVC的各种身份认证方式都是可以在web.config中灵活配置的。以
Windows身份认证为例,其配置如下面的代码所示。
<system.web>
<authentication mode=”Windows”></authentication>
</system.web>
Forms认证采用Cookie来维护页面之间的状态。在ASP.NET MVC中,提供了
一个FormsAuthentication类专门用于身份验证服务,功能之一是写入一个标识用户身份的Cookie,该类的主要成员如表11-2所示。
表11-2 FormsAuthentication的主要成员 | |
属性 | 说明 |
bool IsEnabled | 获取一个值,该值指示是否启用了 Forms身份验证 |
string LoginUrl | 获取用户访问而且认证不通过时,将重定向到登录页的URL |
TimeSpan Timeout | 获取身份验证票证到期前的时间量 |
方法 | 说明 |
FormsAuthenticationTicket Decrypt(string encryptedTicket) | 将加密过的用户身份票证字符串解密成一个FormsAuthenticationTicket对象。其中FormsAuthenticationTicket为用户身份标识类,可以获取保存的用户相关数据. |
string Encrypt(FormsAuthenticationTicket ticket) | 将FormsAuthenticationTicket对象加密成一个字符串 |
void SetAuthCookie( string username, bool createPersistentCookie); | 为提供的用户名创建身份验证票证,并将该票证添加到响应的Cookie集合中或URL中。第一个参数为用户名 |
void SignOut() | 从浏览器删除Forms身份验证票证 |
SetAuthCookie()方法的第2个参数的值为True时,表示生成永不过期的
Cookie,只要用户登录后,以后都不需要重新登录,除非客户端主动把Cookie
清除。
注意到FormsAuthentication提供了LoginUrl和Timeout等一些只读的属
性,实际上这些属性值是可以通过web.config配置的,如下所示。其中timeout
为2880秒,意味着Cookie 2天的有效期。
<system.web>
<authentication mode=”Windows”>
<forms loginUrl=”~/Account/Login” timeout=”2880”/>
</authentication>
</system.web>
11.1.2使用Authorize特性授权
public ActionResult Index()
{
if (this.User.Identity.IsAuthenticated)//具备身份标识
{
//获取写入的userName
string userName = this.User.Identity.Name;
}
return View();
}
[Authorize]
public class HomeController : Controller
资料:事实上Authorize特性包含Users和Roles两个属性,用于提供基于用户和角色的授权,其中多个用户或角色使用“,”分割。
11.2 网站错误处理和友好提示
11.2.1 web.config错误处理配置
示例:
<customErrors defaultRedirect=”~/ErrorPage.htm”
mode=”Remote Only”>
<error statusCode=”404” redirect=”FileNotFound.htm”/>
</customErrors>
这段代码处在配置文件中的<system.web>节中。
其中:
>defaultRedirect代表发生错误时,浏览器重定向到的URL
>mode指示启用(On)、禁用(Off)自定义错误,只让其显示给远程计算机
(RemoteOnly)。
>error子标签用于定义特殊的错误,有以下两个属性。
& statusCode: Http错误的状态码,例如,403为已禁止访问、404为文件未找到、500为内部服务器错误等。
& redirect: 用于指定当前状态的错误发生时,重定向到的页面的URL。
11.2.2 使用HandError处理错误
针对Index()内部可能出现的错误,统一把代码放置在try{}块中,当出现
异常时,则输出名为”Error”的视图,并传递错误对象,这种处理方式并不理想,在ASP.NET MVC中,借助于错误处理特性HandleError,异常处理的代码将
能够从业务代码中分离出来。HandleError的主要成员如表11-3所示。
表11-3 HandleError特性成员表 | |
属性 | 说明 |
Type ExceptionType | 获取或设置异常的类型 |
string View | 获取或设置用于显示异常信息的视图 |
string Master | 获取或设置用于显示异常信息的母版视图 |
示例:
[HandleError(ExceptionType=typeof(Exception),View="Error")]
public ActionResult Index()
{
return View();
}
在发生异常时,ASP.NET MVC在执行的上下文查找”Error”视图(创建在当前Controller对应的View文件夹中或Shared文件夹中),并呈现给用户,在这种情况下,web.config中定义的错误处理配置将失效。
提示:如果处理的异常时System.Exception类型,ExceptionType属性设置可以省略;错误视图名称是”Error”,View的属性设置也可以省略。
如果需要在自定义的“Error”视图中显示详细的错误信息,则依赖于
HandleError封装的错误信息。本质上,HandleError特性在对应的动作方法发
生异常时,会将异常相关的信息封装成一个HandleErrorInfo类型的对象,然后
在传递给“Error”视图。HandleErrorInfo类包含的成员如表11-4所示。
表11-4 HandleErrorInfo类型成员表 | |
成员 | 说明 |
string ActionName | 可获取动作方法的名称 |
string ControllerName | 可获取控制器的名称 |
Exception Exception | 可获取异常对象 |
示例:
@model HandleErrorInfo
@*代码省略*@
11.3 使用缓存提高性能
缓存是ASP.NET MVC内置的功能,由.NET框架提供,使用起来非常方便。
11.3.1 为什么需要缓存
毋庸置疑,使用缓存技术大大提高了数据访问的效率,但是其缺点也非常明
显,即数据过期问题。为了应对不同情况下对缓存实时性的要求,ASP.NET MVC
推出了以下两种缓存技术:应用程序缓存和输出缓存。
11.3.2 应用程序缓存
ASP.NET MVC默认提供的最常用的缓存机制是应用程序缓存,通过Cache对
象完成。
1. 添加缓存
(1)指定键和值
(2)使用Add()方法
(3)使用Insert()方法
2.检索缓存
3.删除应用程序数据缓存对象
(1)自动删除
(2)显示删除
Cache.Remove(“test1”);
11.3.3 输出缓存
表11-5 OutputCache特性的主要属性 | |
属性 | 说明 |
int Duration | 获取或设置缓存持续时间,单位为秒 |
string VaryByParam | 获取或设置基于参数变化的值,可随参数改变缓存,多个参数可以以分号分隔;可设置为”None”标识无参数 |
string VaryByHeader | 获取或设置基于Http头变化的值,随Http头改变缓存 |
string VarByContentEncoding | 获取或设置内容变化的编码 |
string CacheProfile | 获取或设置缓存配置文件名称,支持在web.config中配置缓存参数。 |
11.4 过滤器
11.4.1 过滤器简介
过滤器本质就是对动作方法的执行过程进行干预,这种干预可以影响动作方法执行的各个过程,他和Struts中的拦截器有类似的作用。
接口类型 | 方法 | 说 明 |
IActionFilter | void OnActionExecuted( ActionExecutedContext filterContext) | 在执行动作方法后调用 |
void OnActionExecuting( ActionExecutingContext filterContext) | 在执行动作方法前调用 | |
IResultFilter | void OnResultExecuted( ResultExecutedContext filterContext) | 在操作结果执行之后调用 |
void OnResultExecuting( ResultExecutingContext filterContext) | 在操作结果执行之前调用 | |
IExceptionFilter | void OnException(ExceptionContext filterContext) | 在发生异常时调用 |
IAuthorizationFilter | void OnAuthorization( AuthorizationContext filterContext) | 在需要授权时调用 |
11.4.2 自定义过滤器
实现自定义的过滤器特性,需要满足两个要求。一是实现表11-6中任意的
接口;二是继承FilterAttribute,标识它是一个过滤器特性。
示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace FilterApp.Filters
{
public class LoggerFilter : FilterAttribute, IActionFilter
{
public
void WriteLog(string message)
{
string file = HttpContext.Current.Server.MapPath("~/Content/log.txt");
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(file, true))
{
sw.WriteLine(message);
}
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
string mess = "开始执行控制器{0}的方法{1} 时间{2}......";
WriteLog(string.Format(mess, filterContext.Controller, filterContext.ActionDescriptor.ActionName, DateTime.Now));
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
string mess = "控制器{0}的方法{1} 执行完毕";
WriteLog(string.Format(mess, filterContext.Controller, filterContext.ActionDescriptor.ActionName));
}
}
}
过滤器的作用范围不仅可以作用于动作方法上,还可以有更大的范围,包括:
(1)应用到Controller类上,则对Controller类的所有动作方法有效;
(2)应用到整个程序中,则对程序中所有动作方法有效。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
public class HomeController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
//定义日志文件路径
string filePath = filterContext.HttpContext.Server.MapPath(@"~log.txt");
//省略其它代码...
}
}
11.4.3应用多个过滤器
1.类上的过滤器优先于方法上的过滤器
2.按Order属性值的大小从小到大执行
它的默认值是-1
3.控制器重写的过滤器接口方法优先执行