在配置文件中注册HTTP模块
当我们建立了HTTP模块并把它复制到Web应用程序的bin目录或者全局部件缓沖(Global Assembly Cache)之后接下来就应该在nfig或nfig中注册它了
我们可以使用<httpModules>和<add>节点把HTTP模块添加到Web应用程序中实际上模块都使用<add>节点列举在<httpModules>和</httpModules>节点之内了
因为配置设置信息是可以继承的所以子目录从父目录那儿继承配置设置信息其结果是子目录可能继承了一些不需要的HTTP模块(它们是父配置信息的一部分)因此我们需要一种删除这些不需要的模块的方法我们可以使用<remove>节点如果我们希望删除从应用程序继承得到的所有HTTP模块可以使用<clear>节点
下面的代码是添加HTTP模块的一个通用示例
<httpModules>
<add type=classname assemblyname name=modulename />
<httpModules>
下面的代码是从应用程序中删除HTTP模块的一个通用示例
<httpModules>
<remove name=modulename />
<httpModules>
在上面的XML中
· Type属性用类和部件名称的形式指定了HTTP模块的实际类型
· Name属性指定了模块的友好名称其它应用程序可以使用这个名称来识别HTTP模块
ASPNET运行时如何使用HTTP模块
ASPNET运行时使用HTTP模块实现某些特殊的功能下面的片段来自于nfig文件它显示了ASPNET运行时安装的HTTP模块
<httpModules>
<add name=OutputCache type=SystemWebCachingOutputCacheModule/>
<add name=Session type=SystemWebSessionStateSessionStateModule/>
<add name=WindowsAuthentication
type=SystemWebSecurityWindowsAuthenticationModule/>
<add name=FormsAuthentication
type=SystemWebSecurityFormsAuthenticationModule/>
<add name=PassportAuthentication
type=SystemWebSecurityPassportAuthenticationModule/>
<add name=UrlAuthorization
type=SystemWebSecurityUrlAuthorizationModule/>
<add name=FileAuthorization
type=SystemWebSecurityFileAuthorizationModule/>
</httpModules>
ASPNET使用上面一些HTTP模块来提供一些服务例如身份验证和授权对话管理和输出缓沖由于这些模块都注册在nfig文件中
实现一个提供安全服务的HTTP模块
现在我们实现一个HTTP模块它为我们的Web应用程序提供安全服务该HTTP模块基本上是提供一种定制的身份认证服务它将接收HTTP请求中的身份凭证并确定该凭证是否有效如果有效与用户相关的角色是什么?通过UserIdentity对象它把这些角色与访问我们的Web应用程序页面的用户的标识关联起来
下面是该HTTP模块的代码
using System;
using SystemWeb;
using SystemSecurityPrincipal;
namespace SecurityModules
{
/// Class的总体描述
public class CustomAuthenticationModule : IHttpModule
{
public CustomAuthenticationModule()
{
}
public void Init(HttpApplication r_objApplication)
{
// 向Application 对象注册事件处理程序
r_objApplicationAuthenticateRequest +=
new EventHandler(thisAuthenticateRequest) ;
}
public void Dispose()
{
// 此处空出因为我们不需要做什么操作
}
private void AuthenticateRequest(object r_objSenderEventArgs r_objEventArgs)
{
// 鑒别用户的凭证并找出用户角色
HttpApplication objApp = (HttpApplication) r_objSender ;
HttpContext objContext = (HttpContext) objAppContext ;
if ( (objAppRequest[userid] == null) ||
(objAppRequest[password] == null) )
{
objContextResponseWrite(<H>Credentials not provided</H>) ;
objContextResponseEnd() ;
}
string userid = ;
userid = objAppRequest[userid]ToString() ;
string password = ;
password = objAppRequest[password]ToString() ;
string[] strRoles ;
strRoles = AuthenticateAndGetRoles(userid password) ;
if ((strRoles == null) || (strRolesGetLength() == ))
{
objContextResponseWrite(<H>We are sorry but we could not
find this user id and password in our database</H>) ;
objAppCompleteRequest() ;
}
GenericIdentity objIdentity = new GenericIdentity(userid
CustomAuthentication) ;
objContextUser = new GenericPrincipal(objIdentity strRoles) ;
}
private string[] AuthenticateAndGetRoles(string r_strUserIDstring r_strPassword)
{
string[] strRoles = null ;
if ((r_strUserIDEquals(Steve)) && (r_strPasswordEquals(seconds)))
{
strRoles = new String[] ;
strRoles[] = Administrator ;
}
else if ((r_strUserIDEquals(Mansoor)) && (r_strPasswordEquals(mas)))
{
strRoles = new string[] ;
strRoles[] = User ;
}
return strRoles ;
}
}
}
我们研究一下上面的代码
我们是从Init函数开始的这个函数把处理程序的AuthenticateRequest事件插入Application(应用程序)对象的事件处理程序列表中这将导致引发AuthenticationRequest事件的时候Application调用该方法
我们的HTTP模块初始化之后我们就可以调用它的AuthenticateRequest方法来鑒别客户端请求AuthenticateRequest方法是该安全/身份认证机制的核心在这个函数中
和行提取HttpApplication和HttpContext对象到行检测是否没有给我们提供了用户id或密码如果没有提供就显示错误信息请求处理过程终止
到行从HttpRequest对象中提取用户id和密码
行调用一个叫做AuthenticateAndGetRoles的辅助(helper)函数这个函数主要执行身份验证并决定用户角色上面的代码采用了硬编码(hardcoded)只允许两个用户使用但是我们可以扩展这个方法并添加代码与用户数据库交互操作并检索用户的角色
到行检测是否有角色与用户关联如果没有就意味着传递给我们的凭证没有通过验证因此该凭证是无效的因此给客户端发送一个错误信息并且请求结束了
和行非常重要因为这两行实际上告诉ASPNET HTTP运行时已登录用户的身份这两行成功执行以后我们的aspx页面就能够使用User对象访问这些信息了
现在我们看一看这种身份验证机制的运行情况目前我们只允许下面两个用户登录到系统
· User id = Steve Password = seconds Role = Administrator
· User id = Mansoor Password = mas Role = User
注意用户id和密码是大小写敏感的(区分大小写)
首先试图不提供凭证登录系统在IE中输入x将看到下面的消息
现在试图使用用户idSteve和密码seconds登录系统输入 x?userid=Steve&password=seconds你将看到下面的欢迎消息
现在试图使用用户idMansoor和秘码mas登录系统输入x?userid=Mansoor&password=mas你将看到下面的欢迎消息页面
现在试图使用错误的用户id和密码组合来登录系统输入x?userid=Mansoor&password=xyz你将看到下面的错误消息
这表明我们的安全模块在起作用了你可以通过在AuthenticateAndGetRoles方法中使用数据库访问代码来扩展该安全模块
要使所有的部分都起作用我们必须对nfig文件进行一些修改首先由于我们要使用自己的身份验证因此不需要其它的身份验证机制为了达到这个目的改变webapp的nfig文件中的<authentication>节点如下所示
<authentication mode=None/>
类似地不允许匿名用户访问我们的Web站点给nfig文件添加下面的语句
<authorization>
<deny users=?/>
</authorization>
用于至少能够匿名访问用于提供凭证的文件在nfig文件中使用下面的配置设置信息把indexaspx作为唯一能够匿名访问的文件
<location path=indexaspx>
<systemweb>
<authorization>
<allow users=*/>
</authorization>
</systemweb>
</location>
结论
你可能已经意识到有了HTTP处理程序和模块后ASPNET已经给开发者提供了强大的能量把你自己的组件插入ASPNET请求处理管道享受它的优点吧
作为练习你应该进一步改进程序使示例身份验证模块更加灵活并能根据用户的需要进行调整