mvc基础系列说谈(9)——修饰标签(修饰属性,过滤器)(中)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 在上一篇中,介绍了 AcceptVerbs,ActionName,NonAction,OutputCache,ValidateInput,HandleError这几个修饰标签。它们的父类有所不同。例如: AcceptVerbs 标签(类)从ActionMethodSelectorAttribute类派生;NonAction从ActionMethodSelectorAttribute派生。

在上一篇中,介绍了

AcceptVerbsActionNameNonActionOutputCacheValidateInputHandleError这几个修饰标签。它们的父类有所不同。例如:

AcceptVerbs 标签(类)从ActionMethodSelectorAttribute类派生;NonActionActionMethodSelectorAttribute派生。

 

然后,如HandleError它的定义是这样的:

public   class  HandleErrorAttribute : FilterAttribute, IExceptionFilter
{
    
// Fields
     private   const   string  _defaultView  =   " Error " ;
    
private  Type _exceptionType;
    
private   string  _master;
    
private   string  _view; 

    
// Methods
     public  HandleErrorAttribute();
    
public   virtual   void  OnException(ExceptionContext filterContext);

    
// Properties
     public  Type ExceptionType {  get set ; }
    
public   string  Master {  get set ; }
    
public   string  View {  get set ; }
}

 

它继承了FilterAttribute类,且实现了IExceptionFilter 接口。

 

asp.net MVC框架支持以下几类过滤器:
·AuthorizeAttribute
用于实现用户验证及对动作访问的授权。

·Action过滤器

·Result过滤器

·Exception过滤器

并提供以下几个接口:

public   interface  IActionFilter
{
    
//  Methods
     void  OnActionExecuted(ActionExecutedContext filterContext);
    
void  OnActionExecuting(ActionExecutingContext filterContext);
}

 

public   interface  IResultFilter
{
    
//  Methods
     void  OnResultExecuted(ResultExecutedContext filterContext);
    
void  OnResultExecuting(ResultExecutingContext filterContext);
}

 

public   interface  IExceptionFilter
{
    
//  Methods
     void  OnException(ExceptionContext filterContext);
}

 

public   interface  IAuthorizationFilter
{
    
//  Methods
     void  OnAuthorization(AuthorizationContext filterContext);
}

 

另外还有一个标签:

[AttributeUsage(AttributeTargets.Method  |  AttributeTargets.Class, 
Inherited 
=   true , AllowMultiple  =   false )]
public   abstract   class  FilterAttribute : Attribute
{
    
private   int  _order;
    
protected  FilterAttribute();
    
public   int  Order {  get set ; }
}

 

如果要实现一个自定义过滤器,须实现这个标签和一个以上的接口。MVC还提供了一个ActionFilterAttributen属性(类),它已经实现了IActionFilter, IresultFilter这两个接口,然后可以重载它们的方法来自定义过滤器。

(一)日志记录

现在做一个自定义的日志过滤器,用于记录日志。实现的目标很简单:当访问此页时,记录当前的时间。这个直接从ActionFilterAttribute 派生。

在实现之前,得说下执行顺序:

OnActionExecuting – Action执行之前调用。

OnActionExecuted – Action执行之后调用。

OnResultExecuting – Result产生之前调用。

OnResultExecuted

 

现在要做的是在ActionExecuting事件中记录时间,在ResultExecuted事件中记录时间,即在自定义过滤器中重载其中两个方法即可:

public   class  DateLogFilter : ActionFilterAttribute
{
    
public   override   void  OnActionExecuting(ActionExecutingContext filterContext)
    {
        Log(
" ActionExecuting "   +  DateTime.Now.ToString());
    }

    
public   override   void  OnResultExecuted(ResultExecutedContext filterContext)
    {
        Log(
" ResultExecuted  "   +  DateTime.Now.ToString());
    }

    
private   void  Log( string  strMessage)
    {
        strMessage.WriteFile(
@" K:\logs\ " " log.txt " );
    }
}

 

其中的Log方法用于记录内容。

用的时候就是以修饰标签的方式声明即可:

[DateLogFilter]
public  ActionResult NewsList()
{
    ……
}

 

这个简单的日志记录过滤器就完成了。这个日志过滤器的定义是没有多大意义的,它只用来演示自定义过滤器。

(二)实现图片防盗

图片防盗的原理是利用Http头中的Referer键来实现的。对于资源文件来说,它记录资源文件的引用地址:

请见:

http://www.cnblogs.com/jams742003/archive/2010/02/01/1660917.html

 

例如:http://192.168.1.105:8029/images/a1.gif

这个地址有一个a1.gif图片资源文件。而在另一个站中引用时:

<img src="http://192.168.1.105:8029/images/a1.gif" />

此时的Http头中截取部分键对:

·(Request-Line):GET /images/a1.gif HTTP/1.1
·Host:192.168.1.105:8029
·Referer:http://localhost:20372/web2/Test.aspx

 

其中的 Host 为资源的地址,而 Referer 为引用图片的地址。这两个地址不同,所以可以进行防盗处理了。

 

WebForm模型中,通过自定义HttpHandler来实现防盗处理,而HttpHandlerHttp请求的最终处理中心。例如,通过ashx资源文件进行防盗,因为这个类从IhttpHandler派生的。或者直接以HttpHandler来进行全局资源防盗处理。

1)实现IhttpHandler接口

实现public void ProcessRequest(HttpContext context) 这个方法。通过Http上下文来判断Http头中的HostReferer键值:context.Request.UrlReferrer.Host

2)注册Handler 

< httpHandlers >
    
< add  path ="*.gif"  verb ="*"  type ="GifHandler" />
</ httpHandlers >

 

3)在IIS中添加Gif文件映射

以上三项完成后就可以了。

MVC中实现防盗原理也是这样的。

现在还通过以前介绍的方法来实现并通过测试。

现在先看一个图片访问地址:

http://192.168.1.105:8196/Contents/images/a1.gif

这个地址是一张图片,然后,在MVC中,按路由来分析一下它的情况:

当访问这个地址时(URL),会路由到Contents控制器,并执行images动作,且向这个动作传递了一个a1.gif的字串参数。于是分别创建:

(01)控制器Contents

public  ActionResult images( string  strFilename)
{
    
return  File( " http://www.cnblogs.com/content/images/ " + strFilename,  " image/gif " );
}

 

这张图片放在content文件夹中的images文件夹中

这个动作就是返回图片文件。其中File方法是控制器的一个方法,用于返回ActionResult类型对象。

(02)过滤器

自定义过滤器,可以直接从ActionFilterAttribute类派生,重载它的方法。这里只重载OnActionExecuting这个方法。

实现为:

public   override   void  OnActionExecuting(ActionExecutingContext filterContext)
{
    HttpContextBase httpContext 
=  filterContext.HttpContext;
    
if  ( null   !=  httpContext.Request.UrlReferrer)
    {
        
string  serverDomain  =  httpContext.Request.Url.Host;
        
string  refDomain  =  httpContext.Request.UrlReferrer.Host; 

        
if (serverDomain.Contains(refDomain))
        {
           
return ; // 如果根域名相同就返回
         }

        ContentResult cr 
=   new  ContentResult();
        
if  (FileType  ==  FileType.Image)
        {
           cr.ContentType 
=   " image/jpeg " ;
           FileInfo fi 
=   new  FileInfo(httpContext.Server.MapPath( " ~/Content/images/z1.gif " )); 
           httpContext.Response.WriteFile(fi.FullName);
        }

        filterContext.Result 
=  cr;
    }    

}

 

现在分析一下这个方法:

原理很简单,在Http请求时,资源文件和html是分步进行,例如,一张html中带有一张图片,那么,它会先请求html,然后请求图片,这个在

http://www.cnblogs.com/jams742003/archive/2010/02/01/1660917.html

中已经分析过。在第一次请求中,在http头中hostreferer两个键值并不是全有的,也就是在第二次请求中(请求图片)时,两个值才全有。那么,如果第一次请求时(请求html),那么要判断:

if (null != httpContext.Request.UrlReferrer)

如果不为无(一般我把null叫做无,而不叫空),那么才确定是资源请求。

 

然后:

string  serverDomain  =  httpContext.Request.Url.Host;
string  refDomain  =  httpContext.Request.UrlReferrer.Host;

 这两句用于得到HostReferer键值

于是,如果是本网站访问的,那么两个值应该相等(这两个值要分析,它们的主体部分应该相同),这里粗略的判断:

if (serverDomain.Contains(refDomain))
{
    
return ; // 如果根域名相同就返回
}

 

如果两部分相同,那么直接返回即可,不再做处理。

如果不相同,说明是别的网站访问的,那么:

if  (FileType  ==  FileType.Image)
{
    cr.ContentType 
=   " image/jpeg " ;
    FileInfo fi 
=  
    
new  FileInfo(httpContext.Server.MapPath( " ~/Content/images/z1.gif " ));
    httpContext.Response.WriteFile(fi.FullName);

}

 

如果是图片的话,返回防盗图片给他即可。这里的contenttype并不严格。

这个过滤器是以修饰标签形式声明。

(03)为动作添加修饰

[SelfFilter(FileType.Image)]
public  ActionResult images( string  strFilename)
{
   
return  
   File(
" http://www.cnblogs.com/content/images/ " + strFilename,  " image/gif " );
}

 

现在就是这种情况,其中SelfFilter是自定义的过滤器(一个从ActionFilterAttribute派生的属性类),

为这个属性类还要添加一个一个参数的构造器,它是FileType枚举类型。

public  SelfFilter(FileType fileType)
{
    
this .FileType  =  fileType;
}

 

(04)测试

在一个别的网站中添加文件,文件内容为:

< form  id ="form1"  runat ="server" >
    
< div >
        
< img  src ="http://192.168.1.105:8196/Contents/images/a1.gif"   />
    
</ div >
</ form >

 

然后会发现,显示的是一张防盗图片。

 

博客园大道至简

http://www.cnblogs.com/jams742003/

转载请注明:博客园

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
XML 前端开发 Java
Spring MVC拦截器和过滤器的区别
你好看官,里面请!今天笔者讲的是Spring MVC拦截器和过滤器的区别。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。
175 2
Spring MVC拦截器和过滤器的区别
|
前端开发 Java
springMvc32-原生apiSpring MVC过滤器-HiddenHttpMethodFilter
springMvc32-原生apiSpring MVC过滤器-HiddenHttpMethodFilter
65 0
|
前端开发
.Net Mvc中Filter过滤器需要注意的坑
<p>  啥也不说,先上代码:</p> <p>  public class ValidateAttribute : ActionFilterAttribute</p> <p>  {</p> <p>  private string _Name=null;</p> <p>  //Action执行前的过滤器</p> <p>  public override void OnActionExecuting(ActionExecutingContext filterContext)</p>
127 0
|
前端开发 .NET 开发框架
|
前端开发
|
前端开发 .NET 开发框架
|
前端开发 .NET 开发框架