注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天涯倦客的博客

祝福你朋友永远快乐!

 
 
 

日志

 
 

使用Forms Authentication实现用户注册、登录(二)  

2011-11-30 17:35:41|  分类: asp.net |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

 

  由此,我们在MasterPage的后台代码中添加Page_Init方法,在页面初始化时判断用户是否登录,并显示对应的Panel控件;此外,在用户已登录时,在pnlLoggedin中的欢迎语里插入已登录用户的用户名。
 protected void Page_Init(object sender, EventArgs e)
{
     // 判断用户是否已登录。
     if(HttpContext.Current.User.Identity.Name == "")
     {
         // 用户未登录。
         pnlAnonymous.Visible = true;
         pnlLoggedin.Visible = false;
     }
     else
     {
         // 用户已登录。
         pnlAnonymous.Visible = false;
         pnlLoggedin.Visible = true;

         lblUserName.Text = HttpContext.Current.User.Identity.Name;
     }
}
 
  此外,我们还向项目中添加了default.aspx、login.aspx、register.aspx、test.aspx这样四个页面。其中test.aspx用于检验重定向到登录页后的ReturnUrl参数值,和登录后回到之前页面的效果。
 
用户注册
 
  用户注册部分并不属于验证的范畴,因此Forms Authentication也没有提供过多的支持。然而用户注册是比较简单的,只需通过一个页面搜集用户信息,并存放到数据库中即可。在这个示例中,为了方便和突出真正要讨论的内容,用户信息并不是真的放到数据库中的,而是放在一个集合里,不过通过一个DataAccess类来隐藏这种差异。理论上,一旦关闭应用程序并重新开启,放在集合中的数据就会丢失。然而实际上,再重复运行这里的示例时,用户数据并不会丢失,即便应用程序有所改动也是。这是因为ASP.NET 2.0对于Web项目都是动态重新编译的,应用程序从未直接终止过。
 
  此外,就用户的数据实体类而言,我们仅提供了注册、登录所必需的属性——用户名、密码散列值、密码Salt值。
 
  为了进行用户注册,我们建立了register.aspx页面,该页面仅负责搜集用户信息,真正的创建用户动作在App_Code下的Membership类中完成。注意,此Membership非彼Membership,与ASP.NET 2.0 Membership没有任何关系。
 
  首先在Membership类中添加一个静态方法CreateUser,用于创建用户。该方法完成用户实体的创建和密码的散列等功能。其代码如下所示:
 
 
 public static void CreateUser(string userName, string password)
{
     UserObject user = new UserObject();
     user.Name = userName;
     user.PasswordSalt = GenerateSalt();
     user.PasswordHash = EncodePassword(password, user.PasswordSalt);

     DataAccess.AddUser(user);
}

 这段代码非常简单,其中用到了GenerateSalt和EncodePassword方法,这两个方法用于完成salt值的生成和密码的加salt散列。其代码抽取自MembershipProvider类,进行了精简如下所示:
 public const string PasswordHashAlgorithmName = "SHA1";

static string EncodePassword(string password, string salt)
{
     byte[] src = Encoding.Unicode.GetBytes(password);
     byte[] saltbuf = Convert.FromBase64String(salt);
     byte[] dst = new byte[saltbuf.Length + src.Length];
     byte[] inArray = null;
     Buffer.BlockCopy(saltbuf, 0, dst, 0, saltbuf.Length);
     Buffer.BlockCopy(src, 0, dst, saltbuf.Length, src.Length);

     HashAlgorithm algorithm = HashAlgorithm.Create(PasswordHashAlgorithmName);
     inArray = algorithm.ComputeHash(dst);

     return Convert.ToBase64String(inArray);
}

static string GenerateSalt()
{
     byte[] data = new byte[0x10];
     new RNGCryptoServiceProvider().GetBytes(data);
     return Convert.ToBase64String(data);
}
 
    然后在register.aspx页面中创建搜集用户信息的表单,这个表单非常简单,仅需在ContentPlaceHolder1内添加如下代码:
 <table>
<tr>
<td>用户名:</td>
<td><asp:TextBox ID="txtUserName" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>密码:</td>
<td><asp:TextBox ID="txtPassword" runat="server" TextMode="Password"></asp:TextBox></td>
</tr>
<tr><td colspan="2"><asp:Button ID="btnOK" runat="server" Text="确定"
         onclick="btnOK_Click" /></td></tr>
</table>
<asp:Label ID="lblMessage" runat="server"></asp:Label>
 
注意这比实际的注册页要简单许多,没有对用户名和密码的格式做验证,也没有让用户重复输入密码以确保没有键入错误。
 
  在“确定”按钮的事件处理器中添加如下代码,完成注册功能:
 protected void btnOK_Click(object sender, EventArgs e)
{
     try
     {
         Membership.CreateUser(txtUserName.Text, txtPassword.Text);

         lblMessage.Text = "用户创建成功!";
     }
     catch(Exception ex)
     {
         lblMessage.Text = "错误:" + ex.Message;
     }
}

 用户登录
 
  用户登录大致由下面几个步骤完成:
 ?根据用户名取得与用户相关的信息(用户实体对象);
?判断用户密码是否正确;
?设置用户凭据Cookie并重定向到登录前页面。
 
 
 
  我们主要还是在Membership类中来完成这些工作。为Membership类添加一个Login方法:
 public static void Login(string userName, string password, bool rememberMe)
{
     // 获取用户。
     UserObject user = DataAccess.GetUserByName(userName);
     if(user == null)
         throw new ArgumentException("用户不存在!", "UserName");

     // 检查密码是否正确。
     string pwdHash = EncodePassword(password, user.PasswordSalt);
     if(pwdHash != user.PasswordHash)
         throw new ArgumentException("密码错误!", "Password");

     // 设置安全Cookie并进行重定向。
     FormsAuthentication.RedirectFromLoginPage(userName, rememberMe);
}

 
  这里重点在于检查密码,不过其工作方式已经在上一篇文章中介绍过了,此处不再赘述。读者应该注意到,对密码进行散列使用的是已经存放在数据实体中的Salt值,而不是重新生成Salt值。
 
  这段示例代码通过抛异常来返回错误信息。读者在实际编写这个方法时,可以创建多个Exception类的派生类,分别表示不同的错误;或者采取其他无需抛异常的方式。这一点仁者见仁,智者见智。
 
  接下来,提供一个简单的登录页,完成收集用户名和密码的工作。login.aspx页面的结构也很简单,只需在<ContentPlaceHolder1>中添加下列代码:
 <table>
<tr>
<td>用户名:</td>
<td><asp:TextBox ID="txtUserName" runat="server"></asp:TextBox></td>
</tr>
<tr><td>密码:</td>
<td><asp:TextBox ID="txtPassword" runat="server" TextMode="Password"></asp:TextBox></td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="btnLogin" runat="server" Text="登录" onclick="btnLogin_Click" />
<asp:CheckBox ID="chkRememberMe" runat="server" Text="记住我" />
</td></tr>
</table>
<asp:Label ID="lblMessage" runat="server"></asp:Label>
 

--------------------------------------------------------------------------------

  评论这张
 
阅读(908)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017