All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
PHP技巧:动态URL静态化_[PHP教程]
在ASP.NET中自动给URL加上超级链接_[Asp.Net教程]
SQL Server安装挂起错误解决方式_[SQL Server教程]
SQL2005建立自动备份_[SQL Server教程]
用php实现gb2312和unicode(UTF-8)间的编码转换_[PHP教程]
数据库设计正规化的五大范式_[SQL Server教程]
学习动态网页技术PHP中错误处理的一些方法_php资料_编程技术
AJAX之xmlHttp_[AJAX教程]
asp.net,页面事件:顺序与回传_[Asp.Net教程]
简述.net编程中容易出现的错误认识_[Asp.Net教程]
Reading number is top 10 pictures
Perfect small Laurie2
Embarrassing things comic collection2
擦地板的大叔太好了
全球十大灵异酒店
In the world the most mysterious 21 place landscape1
China telecom 114 spokesman MeiYanXu1
A man's favorite things6
各种囧况!玩游戏最不喜欢出现的十件事(点评)
The world's ten biggest attractions of inventory super the moon
Angie Chiu vijara myth1
Download software ranking
Jinling thirteen stock
VC++6.0简体中文版
WebService在.NET中的实战应用教学视频 → 第1集
致我们终将逝去的青春
Unix video tutorial1
Photoshop 8.0图象编辑软件
Take off clothes to survival
超级战舰
Boxer's Top ten classic battle10
C++编程教程第三版
归海一刀 published in(发表于) 2014/1/30 1:07:43 Edit(编辑)
使用Forms,Authentication实现用户注册、登录,(三)用户实体替换_[Asp.Net教程]

使用Forms,Authentication实现用户注册、登录,(三)用户实体替换_[Asp.Net教程]

使用Forms Authentication实现用户注册、登录 (三)用户实体替换_[Asp.Net教程]

IPrincipal和IIdentity


  通过查阅文档,我们可以看到HttpContext.User属性的类型是IPrincipal接口。然而我们知道,接口通常是不能直接访问的,其背后必定隐藏了一个实现了该接口的对象。那么这个实际对象的类型是什么呢?


  让我们在前面示例的MasterPage的Page_Init方法上加一个断点,再次运行程序,可以得到HttpContext.User属性的真正类型是System.Security.Principal.GenericPrincipal。


  查看IPrincipal接口的定义,可以看到它只有一个公开属性——Identity,其类型是这里要提到的另外一个重要接口IIdentity。通过上面的断点跟踪,我们还能知道对于GenericPrincipal而言,其Identity属性的实际类型是GenericIdentity,也是位于System.Security.Principal命名空间中。


  由此,我们引出了.NET Framework中关于Principal(实体)的整个类型系统。所有这些类型都位于mscorlib.dll程序集中,由此也可以看出,这套模型隶属于整个系统的基石。



实现自己的IPrincipal


  要想用自己的实体对象替换HttpContext.User,就必须让自己的实体对象实现IPrincipal接口;通常还必须伴随着实现IIdentity接口。


  目前系统中有的是一个数据实体对象。一般而言,实现IPrincipal接口有一下两种方式——


编写单独的类型实现IPrincipal接口,并在其中包含数据实体对象;


修改数据实体对象使其实现IPrincipal接口。


  对于这两种方式而言,其Identity属性可以通过以下三种方式实现——


使用.NET Framework提供的GenericIdentity;


创建自定义的类,实现Identity接口;


修改数据实体对象或自定义的实体类,让它们同时实现IPrincipal和IIdentity接口。


  对于简单的应用程序而言,通常可以修改数据实体对象,使其同时实现IPrincipal和IIdentity接口。而就复杂的分层架构应用程序,则建议在逻辑层创建分别实现了IPrincipal和IIdentity接口的对象。本文的示例 明显属于前一种情况,因此我们考虑修改作为数据实体类的UserObject类,让其实现两个接口。以下是修改完毕的UserObject类:



public class UserObject : IPrincipal, IIdentity


{


///


/// 用户名。


///


public string Name;



///


/// 密码散列值。


///


public string PasswordHash;



///


/// 密码salt值。


///


public string PasswordSalt;



#region IIdentity Members



public string AuthenticationType


{


get


{


return "Froms";


}


}



public bool IsAuthenticated


{


get


{


return true;


}


}



string IIdentity.Name


{


get


{


return this.Name;


}


}



#endregion



#region IPrincipal Members



public IIdentity Identity


{


get


{


return this;


}


}



public bool IsInRole(string role)


{


return false;


}



#endregion


}



  首先我们来看一下对IIdentity接口的实现。该接口要求三个属性——AuthenticationType、IsAuthenticated和Name。AuthenticationType表示该用户标识所使用的验证类型,这里返回的是“Forms”;IsAuthenticated属性表示当前用户是否已经通过验证(即是否已登录。在这个例子里,我们只针对已登录用户进行实体替换,所以这个属性总是返回true。通常,实际的Web应用程序编写时还有一种习惯,就是为未登录用户(称之为匿名用户)也提供一个用户实体对象,此时就需要为IsAuthenticated提供逻辑,判断用户是否已通过验证了。最后IIdentity接口还要求对象提供一个Name属性,在这里,由于已经存在了Name字段,因此才用“显示接口实现”来提供Name属性,返回对象自身的Name字段即可。


  接下来我们看一下IPrincipal接口的实现。该接口要求提供一个Identity属性和一个IsInRole方法。由于UserObject类本身已经实现了IIdentity接口,因此在Identity属性中直接reutren this即可。因为我们这个示例不涉及用户分组(角色)方面的技术,因此IsInRole方法总是返回false。



用户实体替换


  用户实体替换即使用我们自己编写的类型的实例来替换HttpContext.User属性。实体替换应该发生在HttpApplication的PostAuthenticateRequest事件发生时,因为此时ASP.NET已经从客户端得到了用户凭证Cookie并进行了解密和校验。


  我们既可以编写一个HttpModule来处理PostAuthenticateRequest事件,也可以在Global..asax文件中添加时间处理器。这里为了简单,我们选择在Global.asax中添加如下事件处理器:



void Application_PostAuthenticateRequest(object sender, EventArgs e)


{


HttpApplication app = (HttpApplication)sender;


if(app.Context.User.Identity.Name != "") // 仅在已登录时替换


{


UserObject user = DataAccess.GetUserByName(app.Context.User.Identity.Name);


app.Context.User = user;


Thread.CurrentPrincipal = user;


}


}



  在这里我们首先进行了判断,如果用户已登录,才进行实体替换。当然你也可以选择未未登录用户也提供一个匿名用户实体。


  接下来,我们通过本来已经存放在HttpContext.User.Identity中的用户标识得到了数据实体对象,然后分别将其赋予HttpContext.User和Thread.CurrentPrincipal。


  至此,我们的示例代码就完工了。没有提到的是,完成了这一步之后,你就可以通过类似下面的代码在任何可以访问到HttpContext的地方获取用户实体了:



UserObject user = HttpContext.Current.User as UserObject;


if(user != null)


{


// 可以使用user


}


else


{


// 用户未登录


}



  需要注意,由于在这里我们仅对已登录用户进行了用户实体替换,所以代码使用as进行类型转换并结合if语句进行判断是必需的。



小结


  好吧,这一部分说的是用户实体替换。







添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.