时间:2020-12-19 11:27:53 | 栏目:.NET代码 | 点击:次
下面简单分析UrlAuthorizationModule的源码,便可了解验证模型是如何验证在web.config中指定的授权规则.
UrlAuthorizationModule在应用程序初始化时向HttpApplication::AuthorizeRequest事件(安全模块已验证用户授权时发生)注册委托代码,该代码内部调用AuthorizationConfig::IsUserAllowed.方法实现截图如下:
上面代码又调用了AuthorizationConfigRule::IsUserAllowed方法,截图如下:
由于HttpApplication::AuthorizeRequest事件是在HttpApplication::AuthenticateRequest事件之后执行的(请看我提到过的事件列表), 在前面介绍的AuthenticateRequest事件中我们修改了Context.User对象,而且加入了角色信息,所以AuthorizeRequest事件在验证用户的权限时发现Context.User对象中什么都有,所以它才允许用户访问请求的资源,否则请求将被返回到指定的页面.以上就是ASP.NET1.1的原理,怎么样你理解了吗?
ASP.NET2.0你仍可以用这样的机制,但又增加新特性.下面就看看在ASP.NET2.0中是如何实现的吧!
ASP.NET 2.0 实现方式
ASP.NET2.0的实现方式与ASP.NET1.1实现方式大同小异,同样支持前一版本的安全模型.不过又新增了成员资格与角色管理授权模型.这里就介绍ASP.NET2.0新增的内容.
l 应用程序配置新增属性
<system.web>
<authentication mode="Forms">
//defaultUrl是ASP.NET2.0版本新增的属性, 在验证模型重定向URL时将重定向到的URL.默认值为"default.aspx".
//虽然ASP.NET1.1版本没有该属性,但程序中的默认为"default.aspx".还是ASP.NET2.0的配置更为灵活.
<forms loginUrl="logon.aspx" protection="All" name=".ASPXFORMSAUTH" path="/" defaultUrl="Index.aspx"></forms>
</authentication>
<authorization>
<deny users="?" />/*匿名用户*/
</authorization>
</system.web>
l 使用成员资格验证登录
ASP.NET 成员资格主要用于ASP.NET Forms 身份验证,配合ASP.NET2.0登录控件可以不用写任何代码就能实现Forms身份验证.
首先创建登录页Login.aspx,将登录控件托入到窗体中即可,不用写任何登录事件代码,相比ASP.NET1.1节省时间不是一点半点.
l 使用角色管理进行访问授权
角色管理可以帮助您管理授权,使您能够指定应用程序中的用户可访问的资源.角色管理可让您通过将用户分配到相应角色来对其进行分组,从而更容易控制访问权限.
1. 启用角色管理
要启用该功能,修改web.config文件在<system.web>配置节点内增加子节点如下:
<roleManager enabled="true" cacheRolesInCookie="true" />
cacheRolesInCookie属性代表是否缓存角色信息,这样不用每次都从数据库中获取角色,以提高应用程序的性能.
但是将角色放在Cookie里总是风险的,它可能被篡改,然后用它访问未被授权的资源.
不过可以在用户每次登录时,先使用Role API的DeleteCookie方法删除这个缓存Cookie, 这样可使风险小一点.
推荐代码:
if(Membership.ValidateUser(username, password)){
Roles.DeleteCookie();
FormsAuthentication.RedirectFromLoginPage(username, false);
}
特别提示:应用程序配置中当角色管理可用并且提供者程序为AspNetSqlProvider时, SqlRoleProvider的GetRolesForUser方法会调用System.Web.DataAccess.SqlConnectionHelper类的私有静态方法EnsureSqlExpressDBFile创建一个空的aspnetdb.mdf本地数据库,该数据库包含成员资格与角色管理,所需要的表结构等信息.
2. 配置成员与角色
使用VS2008自带的配置工具设定成员与角色是最简单不过的了,点击菜单栏中的[项目],下拉菜单的最后一项[ASP.NET配置],在弹出窗体中设置成员与角色关系.如下图展示:
在安全选项卡内有管理用户与角色的内容,如下图:
本示例创建了一个用户”iori”与一个角色”Admins”,并且指定了该用户是Admins角色的成员.
另外该工具还会自动创建本地数据库(如果还没创建).与它相关的配置在machine.config文件中指定,如下图所示,你可以更改数据库的文件名,默认为”aspnetdb.mdf”.
好了,通过完成上面的几个步骤,网站内容就己经受到授权机制的保护了,可以用刚刚添加的用户试试登录吧.
相比上一版本,ASP.NET2.0在Forms身份验证里为开发人员节省很多时间,几乎不用开发人员写任何代码,方便了许多,下面让我们一探究竟.
l ASP.NET 2.0 安全模型验证授权的原理
1. 验证原理
在.net1.1中开发人员必须为登录页编写登录事件,用来验证用户输入的用户名与密码是否有效,而ASP.NET 2.0中引入了成员资格提供程序与标准登录服务器控件,它们隐式使用Forms 身份验证,登录控件己经包含了验证用户名的程序逻辑,也就是说登录控件会把用户输入的用户名与密码自动与成员资格数据库中的用户进行匹配,如果成功匹配就将特定Cookie写入客户端.
2. 授权原理
还是拿UrlAuthorizationModule说事儿, 如果不启用角色管理,实现方式与ASP.NET1.1差不多,不过由于ASP.NET2.0加入了角色管理模型,角色管理模型使用两个类: RolePrincipal与RoleManagerModule来实现角色授权.如果应用程序配置的角色管理可用时,这两个新对象将被应用到aspx页面的生命周期中, 由于RoleManagerModule 被初始化时会向HttpApplication对象的事件PostAuthenticateRequest加载委托代码,该代码会将app.Context.User对象包装成RolePrincipal对象.
PostAuthenticateRequest事件是在ASP.NET 2.0中加入的,该事件发生在AuthenticateRequest事件之后,代表安全模块已建立了用户标识,所以在这个事件中使用用户标识重新生成RolePrincipal对象.
下面为委托代码的节选.
......//省略若干代码
HttpApplication application = (HttpApplication) source;
HttpContext context = application.Context;
if (this._eventHandler != null)
{
RoleManagerEventArgs e = new RoleManagerEventArgs(context);
this._eventHandler(this, e);
if (e.RolesPopulated)
{
//判断开发人员是否在Global.asax中写了事件处理程序,如下显示的代码.
/*
//这里演示如何在Global.asax中自定义角色
void RoleManager_GetRoles(object sender, RoleManagerEventArgs e)
{
if (e.Context.Request.IsAuthenticated)
{
e.Context.User = new GenericPrincipal(new GenericIdentity(e.Context.User.Identity.Name), new string[] { "Admins" });
e.RolesPopulated = true;
}
}
*/
//如果e.RolesPopulated为真,代表开发人员自己创建了角色信息,
//RoleManagerModule就不会 生成RolePrincipal 对象了.
return;
}
}
......
if (!(context.User is RolePrincipal))
{
context.User = new RolePrincipal(context.User.Identity);
}
Thread.CurrentPrincipal = context.User;
注意:我们并没有像ASP.NET1.1中那样在AuthenticateRequest事件中生成User对象.但是User对象会在FormsAuthenticationModuleHTTP模块中使用Forms身份验证的特定Cookie重新被包装成一个GenericPrincipal对象(角色为空).
在说明RolePrincipal对象有什么用之前,需要了解这个对象是何时被用到的.
在UrlAuthorizationModule被初始化时中向HttpApplication对象注册的事件AuthorizeRequest被触发.
在这个事件中会调用RolePrincipal对象(就是Context.User)的方法IsInRole, IsInRole方法会自动查找角色提供程序(本示例使用默认提供程序AspNetSqlProvider,数据库为前面自动生成的ASPNETDB.MDF),并验证用户角色,代码截图如下:
而IsUserAllowed方法最终会调用RolePrincipal对角的IsInRole方法来判断当前用户是否拥有某角色,方法截图如下:
以上这些便是ASP.NET2.0成员资格与角色管理实现Forms身份验证的原理与实现,不过默认的成员资格与角色数据库的字段一般并不能满足具体项目的需要.好在ASP.NET 2.0中提供了可扩展提拱程序模型,开发人员可以定制成员资格提供程序与角色管理模型.
结束语
网站应用程序的身份验证和授权方法是一项具有挑战性的任务,而Forms身份验证在网站建设中提供了重要的安全性优势,通过提供用户配置文件以及对角色的支持, 简化了程序员通常需要编写大量代码才能完成的工作.如果读者还有什么问题或者对以上描述有不同的见解,欢迎与我联系互相交流!