浅析《ASP.Net Web 站点高级编程》的登录验证!

ASP.NET 中内置的用户验证支持的功能非常强大,它能够自动地在Context对象中生成一个名为User的属性.
该属性能够让我们访问各种信息,包括用户是否已经验证。验证用户的类型,甚至还有用户名,不管我们是
使用基于表单的验证还是WINDOWS验证,都可以使用由Context对象表示的当前的HttpContext实例中的User对象

.Net FrameWork中提供的Context.User对象与前面介绍的User类不同。Context.User用于验证,
而User类用于某个用户的一般性信息.

.Net(不只是ASP.NET)中的安全机制基于负责人(principal)的概念,Principal对象代表以其名义运行代码的用户的安全
环境,因此,如果我运行程序,负责人就是程序运行期间我的安全环境。低于负责人的级别是身份(identity)
身份代表执行代码的用户。因此,每一个负责人都有一个身份,这种通用的负责人和身份的概念用于基于表单
的验证。Windows验证,甚至在.Net编程的其他用于传递证书给Web站点和远程主机.我们决定不创建自己的安全系统
但是要使用自己的负责人和身份的概念,以便巧妙地吻合于Microsoft已有的安全体系..

以上引用《ASP.NET Web站点高级编程 提出问题-设计方案-解决方案》,以下简称ThePhile(工程名)

ThePhile的验证方式是实现了IPrincipal和Identity接口


HttpContext.User的对象必须实现 System.Security.Principal.Iprincipal接口.

IPrincipal 概述

公共属性
Identity 获取当前用户的标识。

公共方法
IsInRole 确定当前用户是否属于指定的角色。

公共属性Identity又必须实现System.Security.Principal.IIdentity 接口

IIdentity 概述

公共属性
AuthenticationType 获取所使用的身份验证的类型。
IsAuthenticated 获取一个值,该值指示是否验证了用户。
Name 获取当前用户的名称

只要实现了这IPrincipal和IIdentity两个接口.然后分配给HttpContext.User的对象.
就可以判断出是否验证过.IsAuthenticated.或者获取用户名称等.


在ThePhile工程中。继承IPrincipal接口的是PhilePrincipal类(通过HttpContext.User可用)
继承IIdentity接口的是SiteIdentity类(通过HttpContext.User.Identity可用)
注:偶手里的代码此类是叫SiteIdentity。而书上的是PhileIdentity。其实没什么只是个类名. 


先来看看登录页位于Modules\User\Login.aspx

这中登录页的登陆按钮单击事件

None.gif private   void  Submit_Click( object  sender, System.EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {            
InBlock.gif            PhilePrincipal newUser 
= PhilePrincipal.ValidateLogin( EmailAddress.Text, Password.Text );
InBlock.gif            
//这里验证用户.并实现IPrincipal和IIdentity接口
InBlock.gif
            
InBlock.gif            
if (newUser == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                LoginResult.Text 
= "Login failed for " + EmailAddress.Text;
InBlock.gif                LoginResult.Visible 
= true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Context.User 
= newUser;
InBlock.gif                FormsAuthentication.SetAuthCookie( EmailAddress.Text, 
true );                    
InBlock.gif                Response.Redirect(
"/ThePhile/default.aspx");
InBlock.gif                
//登录成功、写Cookie。跳转
ExpandedSubBlockEnd.gif
            }

ExpandedBlockEnd.gif        }

None.gif
None.gif

###修改用户接口来支持验证.
需要修改PhilePage类。
因为此类是Web页的基类.. 继承System.Web.UI.Page

 

None.gif using  System;
None.gif
using  System.Web;
None.gif
using  System.Web.UI;
None.gif
using  System.Diagnostics;
None.gif
using  Wrox.WebModules;
None.gif
None.gif
using  Wrox.WebModules.Accounts.Business;
None.gif
None.gif
namespace  Wrox.ThePhile.Web
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Summary description for PhilePage.
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class PhilePage : System.Web.UI.Page
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{                
InBlock.gif        
public PhilePage()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected override void OnInit(EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//这里重写了OnInit方法
InBlock.gif
            base.OnInit(e);
InBlock.gif            
this.Load += new System.EventHandler(this.PhilePage_Load);
InBlock.gif            
this.Error += new System.EventHandler(this.PhilePage_Error);
ExpandedSubBlockEnd.gif        }

InBlock.gif            
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**////这个是写事件日志方法
InBlock.gif        protected void LogEvent(string message, EventLogEntryType entryType)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (!EventLog.SourceExists("ThePhile.COM"))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                EventLog.CreateEventSource(
"ThePhile.COM""Application");
ExpandedSubBlockEnd.gif            }

InBlock.gif            EventLog.WriteEntry(
"ThePhile.COM", message, entryType);
ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 捕获错误显示
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sender"></param>
ExpandedSubBlockEnd.gif        
/// <param name="e"></param>

InBlock.gif        protected void PhilePage_Error(object sender, System.EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string errMsg;
InBlock.gif            Exception currentError 
= Server.GetLastError();
InBlock.gif
InBlock.gif            errMsg 
= "<link rel=\"stylesheet\" href=\"/ThePhile/Styles/ThePhile.CSS\">";
InBlock.gif            errMsg 
+= "<h1>Page Error</h1><hr/>An unexpected error has occurred on this page. The system " +
InBlock.gif                
"administrators have been notified. Please feel free to contact us with the information " +
InBlock.gif                
"surrounding this error.<br/>"+
InBlock.gif                
"The error occurred in: "+Request.Url.ToString()+"<br/>"+
InBlock.gif                
"Error Message: <font class=\"ErrorMessage\">"+ currentError.Message.ToString() + "</font><hr/>"+
InBlock.gif                
"<b>Stack Trace:</b><br/>"+
InBlock.gif                currentError.ToString();
InBlock.gif
InBlock.gif            
if ( !(currentError is AppException) )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// It is not one of ours, so we cannot guarantee that it has been logged
InBlock.gif                
// into the event log.
InBlock.gif
                LogEvent( currentError.ToString(), EventLogEntryType.Error );
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            Response.Write( errMsg );
InBlock.gif            Server.ClearError();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
InBlock.gif        
private void PhilePage_Load(object sender, System.EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// TODO: Place any code that will take place BEFORE the Page_Load event
InBlock.gif            
// in the regular page, e.g. cache management, authentication verification,
InBlock.gif            
// etc.                                            
InBlock.gif
            if (Context.User.Identity.IsAuthenticated) 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                        
//如果是验证通过的
InBlock.gif
                    
InBlock.gif                
if (!(Context.User is PhilePrincipal))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
// ASP.NET's regular forms authentication picked up our cookie, but we
InBlock.gif                    
// haven't replaced the default context user with our own. Let's do that
InBlock.gif                    
// now. We know that the previous context.user.identity.name is the e-mail
InBlock.gif                    
// address (because we forced it to be as such in the login.aspx page)                
InBlock.gif
                    PhilePrincipal newUser = new PhilePrincipal( Context.User.Identity.Name );
InBlock.gif                    Context.User 
= newUser;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
//此处是当前的Context.User不是PihlePrincipal的。转换一下
InBlock.gif                
//再赋给Context.User
ExpandedSubBlockEnd.gif
            }

ExpandedSubBlockEnd.gif        }

InBlock.gif    
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}


上面是PhilePage类。在Web页调用时继承一下就行了
此处有一个问题。当ASPX页继承此类时。
ContractedBlock.gif ExpandedBlockStart.gif Web 窗体设计器生成的代码 #region Web 窗体设计器生成的代码
InBlock.gif        
override protected void OnInit(EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//
InBlock.gif            
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
InBlock.gif            
//
InBlock.gif
            InitializeComponent();
InBlock.gif            
base.OnInit(e);
ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
InBlock.gif        
/// 此方法的内容。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private void InitializeComponent()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{    
InBlock.gif            
this.Load += new System.EventHandler(this.Page_Load);
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif        
#endregion


请看OnInit方法。是选调用了InitializeComponent()后调用父类的base.OnInit(e)
呵。这里可折腾了好几天。如果这样的话就在页面载入是先调用的是本页的Page_Load()方法
后调用父类的OnInit(e),这样PhilePage的Phile_Load()就形同虚设了。
在Thephile工程中它的页面的OnInit都是base.OnInit(e)在前面.而如果你新建一个页面的话就是在后面了
这可能与.Net版本有关。在书的封面上有Writeen and tested for final release of .Net V1.0
我这没有.Net v1.0所以也无法测试了。所以现在用2003 Vs.Net 的IDe时新建的页想要继承PhilePage需要把这两个方法的默认顺序手动改一下.

再看siteHeader控件.是通过验证显示用户名相关信息。否则显示未登录信息

None.gif private   void  Page_Load( object  sender, System.EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
// Put user code to initialize the page here
InBlock.gif
            Greeting.Text = "Welcome, ";
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**////是否验证过
InBlock.gif            if (Context.User.Identity.IsAuthenticated)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Greeting.Text 
+= "<b>" + Context.User.Identity.Name + "</b>"
InBlock.gif                UserLink.Text 
= "My Account";
InBlock.gif                UserLink.NavigateUrl 
= "/ThePhile/Modules/Users/MyAccount.aspx";
InBlock.gif                SignOut.Visible 
= true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Greeting.Text 
+= "Guest User.";
InBlock.gif                UserLink.Text 
= "Click to Login";
InBlock.gif                UserLink.NavigateUrl 
= "/ThePhile/Modules/Users/Login.aspx";
InBlock.gif                SignOut.Visible 
= false;
ExpandedSubBlockEnd.gif            }
        
ExpandedBlockEnd.gif        }

ExpandedBlockStart.gifContractedBlock.gif            
/**/ ///这是退出
None.gif          private   void  SignOut_Click( object  sender, System.EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            FormsAuthentication.SignOut();
InBlock.gif            Response.Redirect(
"/thephile");
ExpandedBlockEnd.gif        }

这样就实现了登录验证。这里一定要注意的地方是。呵要先启用Forms验证方可使上面的代码奏效

None.gif < identity  impersonate ="true"   />
None.gif    
<!--   AUTHENTICATION 
None.gif          This section sets the authentication policies of the application. Possible modes are "Windows", "Forms", 
None.gif          "Passport" and "None"
None.gif    
-->
None.gif    
< authentication  mode ="Forms" >
None.gif        
< forms  name ="ThePhile"  path ="/"  loginUrl ="/ThePhile/Modules/Users/Login.aspx"
None.gif            protection
="All"  timeout ="30" >
None.gif        
</ forms >
None.gif    
</ authentication >

 


具体的代码请参看ThePhile.早就应该写了。出于自己懒。一看12月快过了一个随笔都没有可不行。
急急忙瞎写了一大堆。有错误和不妥地方请大家见谅!
提前祝所有博客。圣诞快乐!beer_mug.gifpresent.gif74_74.gif

转载于:https://www.cnblogs.com/torome/archive/2006/01/19/319950.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值