ASP.NET底层封装HttpModule实例---FormsAuthentication类的分析
HttpModule是用来注册HttpApplication事件的,实现IHttpModule接口的托管代码模块可以访问该请求管道的所有事件。那么对于我们最常用的ASP.NET Forms身份验证模块是如何底层封装处理的呢?
今天过了一遍ASP.NET生命周期,以前的时候喜欢做各种应用,小程序等,渐渐地就觉得真没意思,因为只要你懂点基本的语法,会用相关的库亦或是框架就行,如果出错就是些许的细节错误,严格来说这不锻炼人,这有点像是温水煮青蛙,当然不能说这不好,这可以帮我们熟练地掌握框架的使用,增加熟练度及相关基础的应用,但是就个人而言老觉得缺点什么...后来想想,我要做的其实就是让别人用我开发的框架,库,我想研究的是框架底层的架构而不是用框架。于是过了一遍生命周期,处了IIS处理请求部分实在不懂之外,对ASP.NET处理请求还是更熟练了,对于不懂得我不会去刻意强求懂,毕竟自己的技术深度,广度摆在那,日后到了时候自然会懂。IIS7较之于之前的版本,其扩增了一个集成模式。IS 7.0 集成管道是一种统一的请求处理管道,它同时支持本机代码和托管代码模块。实现 IHttpModule 接口的托管代码模块可访问该请求管道中的所有事件。例如,托管代码模块可用于 ASP.NET 网页(.aspx 文件)和 HTML 页(.htm 或 .html 文件)的 ASP.NET Forms 身份验证。即使 IIS 和 ASP.NET 将 HTML 页视为静态资源,情况也是如此。
从功能上讲,HttpModule之于ASP.NET,就好比ISAPI Filter之于IIS一样。IIS将接收到的请求分发给相应的ISAPI Extension之前,注册的ISAPI Filter会先截获该请求。ISAPI Filter可以获取甚至修改请求的内容,完成一些额外的功能。与之相似地,当请求转入ASP.NET管道后,最终负责处理该请求的是与请求资源类型相匹配的HttpHandler对象,但是在Handler正式工作之前,ASP.NET会先加载并初始化所有配置的HttpModule对象。HttpModule在初始化的过程中,会将一些功能注册到HttpApplication相应的事件中,那么在HttpApplication整个请求处理生命周期中的某个阶段,相应的事件会被触发,通过HttpModule注册的事件处理程序也得以执行。
所有的HttpModule都实现了IHttpModule接口,下面是IHttpModule的定义。其中Init方法用于实现HttpModule自身的初始化,该方法接受一个HttpApplication对象,有了这个对象,事件注册就很容易了。
ASP.NET提供的很多基础构件(Infrastructure)功能都是通过相应的HttpModule实现的,下面类列出了一些典型的HttpModule:
OutputCacheModule:实现了输出缓存(Output Caching)的功能;
SessionStateModule:在无状态的HTTP协议上实现了基于会话(Session)的状态;
WindowsAuthenticationModule + FormsAuthenticationModule + PassportAuthentication- Module:实现了3种典型的身份认证方式:Windows认证、Forms认证和Passport认证;
UrlAuthorizationModule + FileAuthorizationModule:实现了基于Uri和文件ACL(Access Control List)的授权。
抱着吹毛求疵的学习态度,我研究了一下Forms认证的源码(其实也不是源码,利用reflector查出来的)
看下FormsAuthenticationModule的源码:
看下我们最熟的Init方法:
可以看到,在这里给我们注册了两个HttpApplication管道事件,我们看看AuthenticateRequest事件给我们的解释:
然后我们看看OnEnter这个方法:
随后我们点进去看看OnAuthenticate方法:
private void OnAuthenticate(FormsAuthenticationEventArgs e)
{
HttpCookie cookie = null;
if (this._eventHandler != null)
{
this._eventHandler(this, e);
}
if (e.Context.User == null)
{
if (e.User != null)
{
e.Context.SetPrincipalNoDemand(e.User);
}
else
{
bool cookielessTicket = false;
FormsAuthenticationTicket tOld = ExtractTicketFromCookie(e.Context, FormsAuthentication.FormsCookieName, out cookielessTicket);
if ((tOld != null) && !tOld.Expired)
{
FormsAuthenticationTicket ticket = tOld;
if (FormsAuthentication.SlidingExpiration)
{
ticket = FormsAuthentication.RenewTicketIfOld(tOld);
}
e.Context.SetPrincipalNoDemand(new GenericPrincipal(new FormsIdentity(ticket), new string[]));
if (!cookielessTicket && !ticket.CookiePath.Equals("/"))
{
cookie = e.Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
cookie.Path = ticket.CookiePath;
}
}
if (ticket != tOld)
{
if ((cookielessTicket && (ticket.CookiePath != "/")) && (ticket.CookiePath.Length > ))
{
ticket = FormsAuthenticationTicket.FromUtc(ticket.Version, ticket.Name, ticket.IssueDateUtc, ticket.ExpirationUtc, ticket.IsPersistent, ticket.UserData, "/");
}
string cookieValue = FormsAuthentication.Encrypt(ticket, !cookielessTicket);
if (cookielessTicket)
{
e.Context.CookielessHelper.SetCookieValue('F', cookieValue);
e.Context.Response.Redirect(e.Context.Request.RawUrl);
}
else
{
if (cookie != null)
{
cookie = e.Context.Request.Cookies[FormsAuthentication.FormsCookieName];
}
if (cookie == null)
{
cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue) {
Path = ticket.CookiePath
};
}
if (ticket.IsPersistent)
{
cookie.Expires = ticket.Expiration;
}
cookie.Value = cookieValue;
cookie.Secure = FormsAuthentication.RequireSSL;
cookie.HttpOnly = true;
if (FormsAuthentication.CookieDomain != null)
{
cookie.Domain = FormsAuthentication.CookieDomain;
}
e.Context.Response.Cookies.Remove(cookie.Name);
e.Context.Response.Cookies.Add(cookie);
}
}
}
}
}
}
留心的话,可以发现在这个方法里面所有与Forms表单认证相关的类都涉及到了。因此对于Forms表单认证的处理模块,最重要的就是这个FormsAuthenticationModule类了,在这里面,会把为了解耦操作所创建的类都给用上。不得不说,要我写写不出来,理解下HttpModule管道的实际应用还是可以的,对模块设计有个大概的了解。在这里,这个类不知道会不会让你想起ASP.NET MVC框架下的Authentication Filter这个过滤器,过滤器的实现其实就是利用了Attribute这个特性才实现AOP切面注入,因此,其实这个也应该可以加上Attribute来实现AOP。,当然这是我的猜想哈,不过应该可行。
ASP.NET底层封装HttpModule实例---FormsAuthentication类的分析的更多相关文章
- asp.net登录验证FormsAuthenticationTicket和FormsAuthentication类
登录部分使用的类 FormsAuthentication 为 Web 应用程序管理 Forms 身份验证服务. 配置启用身份验证,WEB.config配置: <system.web> ...
- ASP 调用dll(VB)及封装dll实例
ASP调用dll及封装dll实例,封装为dll可以提供运行效率,加密代码. 打开VB6,新建ActiveX DLL 2.在工程引用中加入Microsoft Active Server Pages Ob ...
- ASP.NET底层与各个组件的初步认识与理解 (转载)
ASP.NET底层的初步认识与理解 最近在国外的网站乱走一通,发现一些比较好的文章,收集整理加于自己的理解,作为笔记形式记录下来,让以后自己有个回忆. ASP.NET是一个非常强大的构建Web应用 ...
- Asp.net底层机制
Asp.net底层就是用户通过输入网址,然后请求IIs服务器的流程,在这个过程中有一个重要的部件就是ISAPI,这是一个底层的win32API,在扩展方面比较困难,多用于接口之间的桥接,.net和II ...
- 深入理解asp.net里的HttpModule机制
刚工作的时候看<asp.net深入解析>,第一次知道HttpModule和HttpHandler.当时对我而言,它们不过就是两个新名词而已,仅仅知道工作原理但是理解的不深刻.随着经验的累积 ...
- [翻译]了解ASP.NET底层架构(八)
原文地址:http://www.cnblogs.com/tmfc/archive/2006/09/04/493304.html [翻译]了解ASP.NET底层架构(完) [翻译]了解ASP.NET底层 ...
- ASP.NET基础之HttpModule学习
最近学习WCF知识时看到有关IIS版本的知识,发现对HttpContext,HttpModule,HttpHandler的内容都不是很了解,这三个也是ASP.NET相对基础的内容,晚上特地花点时间针对 ...
- 【SSM 7】Mybatis底层封装思路
一.基本概述 在前面的博客中介绍到Mybatis的逆向生成工具,为我们生成了每个实体的基本增删改查的代码,那么每个实体都是那么多的代码,我们很容易的发现,有很大的相似性.对于这部分代码,应该予以抽象封 ...
- 【Android】19.3 ContentProvider及安卓进一步封装后的相关类
分类:C#.Android.VS2015: 创建日期:2016-03-08 一.简介 ContentProvider:内容提供程序. Android的ContentProvider与.NET框架的EF ...
随机推荐
- 平时常用的一些java方法,请留意
平时常用的一些java方法,请留意. package com.util; import java.io.BufferedInputStream; import java.io.BufferedWrit ...
- (转)CSS颜色及<a>标签超链接颜色改变
CSS颜色大全 <a>标签超链接颜色改变 A:hover {BACKGROUND-COLOR: #ffccff; COLOR: #0080ff} (hover表示鼠 ...
- Bash中的数学计算
一.整数计算 1.整数 $delare -i num$num=5+5$echo $num10 $num="5 + 8"$echo $num13注意:算式中如果有空格,需要用引号引起 ...
- Spring事务隔离级别
REQUIRED:业务方法需要在一个容器里运行.如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务. NOT_SUPPORTED:声明方法不需要事务.如果方法没有关联到一 ...
- asp.net web api实现图片点击式图片验证码
现在验证码的形式越来越丰富,今天要实现的是在点击图片中的文字来进行校验的验证码,如图 这种验证码验证是验证鼠标是否选中了图片中文字的位置,以及选择的顺序,产生验证码的时候可以提供一组底图,然后随机获取 ...
- 编写高质量代码:改善Java程序的151个建议(第二章:基本类型)
编写高质量代码:改善Java程序的151个建议(第二章:基本类型) 目录 建议21:用偶判断,不用奇判断 建议22:用整数类型处理货币 建议23:不要让类型默默转换 建议24:边界还是边界 建议25: ...
- MiniProfiler使用点滴记录-2017年6月23日11:08:23
1.看似针对同样一段查询表ef达式,重复执行却没有被记录下来.其实这是正常情况,因为ef并没有重复去执行 相同sql查询. 2.MiniProfiler结合MVC过滤器进行 拦截记录Sql,示例代码: ...
- docker registry私有仓库部署
私有仓库服务端:12.40[root@centos7_golang ~]# docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry ...
- 如何查询oracle中的关键字
如何查询oracle中的关键字,执行: select * from v$reserved_words
- Intellij IDEA查看方法的调用栈
在IDEA中,先双击选定要查看的方法,使用快捷键Ctrl+Alt+h,在右侧就会显示该方法的详细信息,再双击右侧的方法,就定位到方法的代码区.如下图: