首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

用户注册、登录和注销这3个功能几乎是每一个网站(或网络应用程序)所必需的功能,特别是网站需要识别用户身份。用户注册可以向用户提供在网站中注册其信息的功能;用户一旦注册之后,该用户可以通过用户登录功能登录到该网站;用户注销向用户提供离开网站的功能,并注销网站识别的当前身份票据。本章将介绍使用ASP.NET 2.0和ASP.NET AJAX技术,以及SQL Server 2005数据库共同实现用户注册、登录和注销的方法。

6.1  用户注册、登录和注销应用程序构成

本节介绍用户注册、登录和注销应用程序AjaxUser的实现原理、组成、配置等。

 6.1.1  用户注册、登录和注销实现原理

用户注册、登录和注销应用程序的实现原理比较简单。新用户可以通过注册功能把自己注册成为应用程序的一个合法用户。已注册的用户可以通过登录功能登录到系统中,并使用注销功能退出系统或应用程序。用户注册、登录和注销的原理图如图6.1所示。

数据库

 

图6.1  用户注册、登录和注销的原理图

 6.1.2  AjaxUser应用程序的组成

用户注册、登录和注销应用程序的名称为AjaxUser,它使用的数据库的名称为AjaxUserDB。在Visual Studio 2005的【解决方案资源管理器】面板中查看该应用程序,如图6.2所示。AjaxUser应用程序的组成元素说明如下:

—  App_Code文件夹包含了2个类文件:ASPNETAJAXWeb.cs和User.cs,它们分别定义了AjaxUserSystem和User类。

—  App_Themes文件夹包含了AjaxUser应用程序的主题和样式文件,如web.css、web.skin等。

—  Bin文件夹包含了AjaxUser应用程序引入的程序集,如AjaxControlToolKit.dll、ASPNETAJAXWeb.ValidateCode.dll等。

—  Login.aspx页面为用户登录页面,将实现用户登录的功能。

—  Logoff.aspx页面为用户提供了注销登录的功能。

—  Register.aspx页面为用户提供了注册页面,该页面能够实现注册新用户的功能。

—  Web.config文件为AjaxUser应用程序的配置文件,它配置了数据库连接字符串、引用的程序集等属性。

图6.2  在【解决方案资源管理器】面板中查看AjaxUser应用程序

 6.1.3  AjaxUser应用程序的配置

AjaxUser应用程序的连接字符串放置在Web.config配置文件的<connectionString>元素中,具体代码如下:

<connectionStrings>

    <add name="SQLCONNECTIONSTRING"

        connectionString="data source=localhost;user id=sa;pwd=123456;

            database=AjaxUserDB"

        providerName="System.Data.SqlClient"/>

</connectionStrings>

AjaxUser应用程序在Web.config配置文件的<controls>元素中还配置了与AJAX服务器控件相关的内容,该内容为AjaxControlToolkit.dll程序集中的控件提供了一个前缀字符串“ajaxToolkit”。因此,在该应用程序中的页面引用AjaxControlToolkit.dll程序集中的控件时,不再需要在每一个页面的HTML代码中添加“<Register>”代码,而是直接使用“ajaxToolkit”前缀来引用AjaxControlToolkit.dll程序集中的控件。<controls>元素的具体代码如下:

<controls>

    <add namespace="AjaxControlToolkit" assembly="AjaxControlToolkit"

        tagPrefix="ajaxToolkit"/>

    ……

</controls>

6.2  创建图文验证模块

图文验证模块能够以图片的形式输出一个验证码,应用程序可以使用该验证码来避免机器人和程序自动登录应用程序。

本节介绍的图文验证模块包含两部分:ValidateCode类库工程和ValidateCode.aspx页面。其中,ValidateCode类库工程将输出一个名称为ASPNETAJAXWeb.ValidateCode.dll的动态程序集;ValidateCode.aspx页面将使用该程序集产生并输出验证码。

 6.2.1  创建ValidateCode类库工程

在Visual Studio 2005集成开发环境中创建ValidateCode类库工程,该工程只包含一个类文件:ValidateCode.cs。在【解决方案资源管理器】面板中查看ValidateCode类库工程,如图6.3所示。下面介绍配置该类库工程的输出文件和默认命名空间的基本方法,其具体步骤如下:

* 在【解决方案资源管理器】面板中,右键单击【ValidateCode】节点,并选择【属性】命令,操作如图6.4所示。

            

图6.3  查看ValidateCode类库工程             图6.4  查看ValidateCode类库工程属性的操作

* 单击【属性】命令,选中【应用程序】选项卡,并分别把程序集名称和默认命名空间两个属性的值设置为“ASPNETAJAXWeb.ValidateCode”和“ASPNETAJAXWeb. ValidateCode.Page”,操作如图6.5所示。

注意:通过上述设置之后,ValidateCode类库工程生成之后,将创建一个程序集,该程序集的名称为ASPNETAJAXWeb.ValidateCode.dll。

ValidateCode.cs类文件定义了ValidateCode类,引入了6个命名空间。其中,该类被包含在ASPNETAJAXWeb.ValidateCode.Page命名空间中,且直接继承于System.Web.UI.Page类。其程序代码如下:

图6.5  设置ValidateCode类库的程序集名称和默认命名空间

using System;

using System.Text;

using System.Drawing;

using System.Drawing.Imaging;

using System.Drawing.Drawing2D;

using System.IO;

namespace ASPNETAJAXWeb.ValidateCode.Page

{

    public class ValidateCode:System.Web.UI.Page

    {

        ……

    }

}

在下述程序代码中,ValidateCode类声明了7个字段(IMAGELENGTHBASE、IMAGEHEIGTH、IMAGELINENUMBER、IMAGEPOINTNUMBER、length、code和VALIDATECODEKEY)和2个属性(Length和Code)。其中,Length属性获取和设置验证码的长度,即字符的数量;Code属性获取验证码。

private const double IMAGELENGTHBASE = 12.5;

private const int IMAGEHEIGTH = 22;

private const int IMAGELINENUMBER = 25;

private const int IMAGEPOINTNUMBER = 100;

public static string VALIDATECODEKEY = "VALIDATECODEKEY";

private int length = 4;

private string code = string.Empty;

/// <summary>

/// 获取或设置验证码长度,默认值为4

/// </summary>

public int Length

{

    get{return length;}

    set{length = value;}

}

/// <summary>

/// 获取验证码

/// </summary>

public string Code

{

    get{return Code;}

}

public ValidateCode()

{

}

……

 6.2.2  创建随机数字串

在下述程序代码中,CreateCode(int length)方法将创建一个由数字组成的、指定长度(由length参数指定)的随机字符串。CreateCode(int length)方法首先创建一个随机对象random,并根据指定的长度,使用for语句创建一个随机数字字符串。最后,将该随机数字字符串保存在Session对象中。

/// <summary>

/// 创建随机验证码

/// </summary>

/// <param name="length">验证码长度</param>

/// <returns></returns>

public string CreateCode(int length)

{

    if(length <= 0) return string.Empty;

    ///创建一组随机数,并构成验证码

    Random random = new Random();

    StringBuilder sbCode = new StringBuilder();

    for(int i = 0; i < length; i++)

    {

        sbCode.Append(random.Next(0,10));

    }

    ///保存验证码到Session对象中

    code = sbCode.ToString();

    Session[VALIDATECODEKEY] = code;

    return code;

}

 6.2.3  绘制带有文字的图像

绘制带有文字的图像由CreateValidateImage(string code)方法实现。其中,code参数指定被输出的随机字符串,即验证图片中显示的文本。CreateValidateImage(string code)方法绘制带有文字的图像的具体步骤如下:

* 判断验证码的合法性,如果为空,则中止该方法。程序代码如下:

/// <summary>

/// 创建验证码的图片和验证码

/// </summary>

/// <param name="code">验证码</param>

public void CreateValidateImage(string code)

{

    if(string.IsNullOrEmpty(code) == true) return;

    ///保存验证码到Session对象中

    Session[VALIDATECODEKEY] = code;

* 根据验证码的长度创建一个Bitmap类型的图像image,同时获取该图像的Graphics对象g。

///创建一个图像

Bitmap image = new Bitmap(

     (int)Math.Ceiling((code.Length * IMAGELENGTHBASE)),

    IMAGEHEIGTH);

Graphics g = Graphics.FromImage(image);

* 创建一个随机数生成对象random,并先清空图像的背景颜色,然后指定图像的背景颜色为白色。使用for语句在image图像上绘制干扰线。

///随机数生成器

Random random = new Random();

try

{   ///清空图像,并指定填充颜色

    g.Clear(Color.White);

    ///绘制图片的干扰线

    int x1,x2,y1,y2;

    for(int i = 0; i < IMAGELINENUMBER; i++)

    {

        x1 = random.Next(image.Width);

        y1 = random.Next(image.Height);

        x2 = random.Next(image.Width);

        y2 = random.Next(image.Height);

        ///绘制干扰线

        g.DrawLine(new Pen(Color.Silver),x1,y1,x2,y2);

    }

* 在image图像上绘制验证码(即code参数的值),并设置绘制的画笔的格式为粗体和斜体。

///绘制验证码

Font font = new Font("Tahoma",

    12,FontStyle.Bold | FontStyle.Italic);

LinearGradientBrush brush = new LinearGradientBrush(

    new Rectangle(0,0,image.Width,image.Height),

    Color.Blue,Color.DarkRed,1.2f,true);

g.DrawString(code,font,brush,2.0f,2.0f);

* 在image图像上绘制前景噪音点。其中,每一个噪音点的起始坐标、颜色都是随机产生的。

///画图片的前景噪音点

int x,y;

for(int i = 0; i < IMAGEPOINTNUMBER; i++)

{

    x = random.Next(image.Width);

    y = random.Next(image.Height);

    ///绘制点

    image.SetPixel(x,y,Color.FromArgb(random.Next()));

}

* 将image图像的边框线设置为Silver,然后绘制image图像的边框线。

///画图片的边框线

g.DrawRectangle(new Pen(Color.Silver),

    0,

    0,

    image.Width - 1,

    image.Height - 1);

* 创建MemoryStream对象ms,并将image图像保存到ms中,同时设置图像保存的格式为Gif。

///保存图片的内容到流中

MemoryStream ms = new MemoryStream();

image.Save(ms,ImageFormat.Gif);

* 首先设置页面的输出格式为“image/Gif”,然后使用页面的Response对象输出保存在ms对象中图像的二进制数据。其中,输出数据的方法为BinaryWrite()方法。

    ///输出图片

    Response.ClearContent();

    Response.ContentType = "image/Gif";

    Response.BinaryWrite(ms.ToArray());

}

* 释放Graphics对象g、image对象所占有的资源。

            finally

            {   ///释放占有的资源

                g.Dispose();

                image.Dispose();

            }

        }

    }

}

ValidateCode类继承于System.Web.UI.Page类,因此,可以把ValidateCode类设置某一个Web窗体页的继承类。下述程序代码重写了System.Web.UI.Page类的OnLoad(EventArgs e)事件。重写之后的方法调用CreateValidateImage(string code)方法创建图文验证的图像,并在页面上输出该图像。

protected override void OnLoad(EventArgs e)

{

    CreateValidateImage(length);

}

如果某一个页面的继承类设置为ValidateCode类,那么该页面首先将页面载入(Load)时调用CreateValidateImage(string code)方法创建图文验证的图像,并在页面上输出该图像。

另外,ValidateCode类还提供了一个公开方式的方法:CreateValidateImage(int length)。该方法可以根据指定长度(由length参数指定)来创建一个随机数字字符串,并创建图文验证的图像,以及在页面上输出该图像。

/// <summary>

/// 创建验证码的图片和验证码

/// </summary>

/// <param name="length">验证码的长度</param>

public void CreateValidateImage(int length)

{   ///创建验证码

    code = CreateCode(length);

    ///创建验证码的图片

    CreateValidateImage(code);

}

 6.2.4  创建图文验证的页面

创建6.2.2和6.2.3小节中的ValidateCode类之后,要创建一个图文验证的页面是非常简单的事情。下面介绍创建图文验证的页面ValidateCode.aspx的具体步骤。

* 在某一个ASP.NET应用程序中添加Web窗体页ValidateCode.aspx,并删除该页面的代码隐藏文件。

* 删除ValidateCode.aspx页面的HTML代码,仅仅保留一行使用“@Page”指令的代码。

* 把该“@Page”指令的代码修改为如下形式的程序代码。同时,将该指令的Inherits属性的值设置为ValidateCode类,即ASPNETAJAXWeb.ValidateCode.Page.ValidateCode类。

<%@ Page Language="C#" AutoEventWireup="false"

    Inherits="ASPNETAJAXWeb.ValidateCode.Page.ValidateCode" %>

注意:图文验证的页面ValidateCode.aspx无任何HTML代码和代码隐藏文件,它的Inherits属性的值为创建验证码的类ASPNETAJAXWeb.ValidateCode.Page. ValidateCode。

 6.2.5  使用图文验证的页面

上述(6.2.1~6.2.4小节)创建的图文验证的ValidateCode.aspx页面可以在任何ASP.NET应用程序中使用。使用的具体方法如下:

* 把ValidateCode.aspx页面复制到要使用该页面的ASP.NET应用程序中。在图6.6中,AjaxUser应用程序把ValidateCode.aspx页面复制其根目录下。

* 使用引用的方式把程序集添加到使用该页面的ASP.NET应用程序中,在图6.7中,单击AjaxUser应用程序的【Bin】节点,选择【添加引用】命令来添加新的引用。

               

图6.6  复制ValidateCode.aspx页面                        图6.7  添加引用操作

* 单击【添加引用】命令,弹出【添加引用】对话框,并选择要添加的程序集ASPNETAJAXWeb.ValidateCode.dll,如图6.8所示。

* 单击【确定】按钮,可以将程序集ASPNETAJAXWeb.ValidateCode.dll添加到AjaxUser应用程序中。此时,在【解决方案资源管理器】中查看AjaxUser应用程序,如图6.9所示。

      

图6.8  【添加引用】对话框                   图6.9  查看添加引用后的程序集

* 在使用验证码的页面上添加一个Image控件,并将该控件的ImageUrl属性的值设置为ValidateCode.aspx页面。

<asp:Image ID="imgCode" runat="server" ImageUrl = "~/ValidateCode.aspx" />

* 检测用户输入的验证码是否正确。不妨设输入验证码的TextBox控件的ID属性的值为tbCode,那么可以使用下述程序代码检查用户输入的验证码是否正确,并在lbMessage控件中显示检测结果。

注意:ValidateCode.aspx页面产生的验证码保存在由关键字“VALIDATECODEKEY”标识的Session对象中。

///判断是否创建了验证码

if(Session[ValidateCode.VALIDATECODEKEY] == null) return;

///验证验证码是否相等

if(tbCode.Text != Session[ValidateCode.VALIDATECODEKEY].ToString())

{

    lbMessage.Text = "验证码输入错误,请重新输入。";return;

}

6.3  智能化用户注册模块

用户注册功能由Register.aspx页面实现,它的代码隐藏文件为Register.aspx.cs。其中,该页面保存在AjaxUser应用程序的根目录下。Register.aspx页面为用户提供注册的功能。

 6.3.1  数据库设计

AjaxUser应用程序使用的数据库的名称为AjaxUserDB,它只包含一个名称为User的表。该表保存用户信息,它包含的字段及其说明如表6.1所示。

表6.1  User表

  

数据类型

字段说明

  

   

ID

int

ID

PK

主键(自动增一)

Username

varchar(50)

用户名称

 

 

Password

varchar(255)

用户密码

 

 

Status

tinyint

标识用户的状态

 

 

 6.3.2  数据访问层设计

AjaxUser应用程序的数据访问层由UserDAL类实现,该类包含在ASPNETAJAXWeb. AjaxUser命名空间中。UserDAL类的代码定义在User.cs类文件中,并且还引入了System.Data.SqlClient命名空间。下面的程序代码声明了UserDAL类,并声明了1个只读变量ConnectionString,该变量从Web.config配置文件中获取访问数据库的连接字符串。其中,UserDAL类中的方法代码已经省略。

using System.Data.SqlClient;

namespace ASPNETAJAXWeb.AjaxUser

{

    /// <summary>

    /// 操作用户信息的数据访问层

    /// </summary>

    public class UserDAL

    {

        /// <summary>

        /// 保存数据库的连接字符串

        /// </summary>

        private readonly string ConnectionString

            = ConfigurationManager.ConnectionStrings[

                "SQLCONNECTIONSTRING"].ConnectionString;

        public UserDAL(){}

        ……

    }

}

在智能化用户注册模块中,它的数据访问层只实现了两个功能:检测用户名称是否被使用和提交用户的注册信息到数据库中。这两个功能分别由CheckUser(string username)和AddUser(String username,String password)方法实现。

CheckUser(string username)方法检测用户即将注册的用户名称(由username参数指定)在数据库中是否存在,即是否被别人注册。声明该方法的程序代码如下:

public SqlDataReader CheckUser(string username)

CheckUser(string username)方法返回类型为SqlDataReader,它使用Pr_CheckUser存储过程从数据库的User表中检测用户名称已经存在记录的数量。该存储过程的程序代码如下:

CREATE PROCEDURE Pr_CheckUser

(

    @Username varchar(50)

)

AS

SELECT COUNT(*) AS UserCount

FROM [User]

WHERE Username = @Username

在下述程序代码中,CheckUser(string username)方法检测username参数指定的名称是否在数据库的User表中存在。该方法的具体实现步骤如下:

* 使用连接字符串ConnectionString创建SqlConnection对象con,该对象用来连接数据库。

* 设置执行的存储过程为Pr_CheckUser,并设置myCommand对象的执行方式为存储过程。

* 添加存储过程需要的@Username参数,并进行赋值。

* 执行存储过程Pr_CheckUser,并将结果保存到SqlDataReader对象dr中。

* 如果上述操作成功,则返回SqlDataReader对象dr。

public SqlDataReader CheckUser(string username)

{   ///定义数据库的Connection 和 Command

    SqlConnection myConnection = new SqlConnection(ConnectionString);

    SqlCommand myCommand = new SqlCommand("Pr_CheckUser",myConnection);

    ///定义访问数据库的方式为存储过程

    myCommand.CommandType = CommandType.StoredProcedure;

    ///创建访问数据库的参数

    SqlParameter parameterUserName

        = new SqlParameter("@Username",SqlDbType.VarChar,50);

    parameterUserName.Value = username;

    myCommand.Parameters.Add(parameterUserName);

    SqlDataReader dr = null;

    try

    {   ///打开数据库的连接

        myConnection.Open();

    }

    catch(Exception ex){throw new Exception("数据库连接失败!",ex);}

    try

    {   ///执行数据库的存储过程(访问数据库)

        dr = myCommand.ExecuteReader(CommandBehavior.CloseConnection);

    }

    catch(Exception ex){throw new Exception(ex.Message,ex);}

    return dr;          ///返回dr

}

AddUser(String username,String password)方法将用户的注册信息(其中,用户名称由username参数指定,用户密码由password参数指定)插入到数据库的User表中。声明该方法的程序代码如下:

public int AddUser(String username,String password)

AddUser(String username,String password)方法返回类型为int,它将返回新用户在User表中的ID值。该方法使用Pr_AddUser存储过程将用户的注册信息插入到数据库的User表中。该存储过程的程序代码如下:

CREATE PROCEDURE Pr_AddUser

(

    @Username varchar(50),

    @Password varchar(255)

)

AS

INSERT INTO [User]

     (Username,Password,Status)

    VALUES

     (@Username,@Password,1)

RETURN @@Identity

在下述程序代码中,AddUser(String username,String password)方法将用户的注册信息插入到数据库的User表中。该方法的具体实现步骤如下:

* 使用连接字符串ConnectionString创建SqlConnection对象con,该对象用来连接数据库。

* 设置执行的存储过程为Pr_AddUser,并设置myCommand对象的执行方式为存储过程。

* 添加存储过程需要的@Username、@Password和@UserID参数。其中,前两个参数为输入类型的参数,后面一个参数为返回类型的参数,它将保存新插入记录的ID值。

* 执行存储过程Pr_AddUser。

* 如果上述操作成功,则返回@UserID参数的值。

public int AddUser(String username,String password)

{   ///定义数据库的Connection 和 Command

    SqlConnection myConnection = new SqlConnection(ConnectionString);

    SqlCommand myCommand = new SqlCommand("Pr_AddUser",myConnection);

    ///定义访问数据库的方式为存储过程

    myCommand.CommandType = CommandType.StoredProcedure;

    ///创建访问数据库的参数

    SqlParameter parameterUserName

        = new SqlParameter("@UserName",SqlDbType.VarChar,32);

    parameterUserName.Value = username;

    myCommand.Parameters.Add(parameterUserName);

    SqlParameter parameterPassword

        = new SqlParameter("@Password",SqlDbType.VarChar,100);

    parameterPassword.Value = password;

    myCommand.Parameters.Add(parameterPassword);

    SqlParameter parameterUserID

        = new SqlParameter("@UserID",SqlDbType.Int,4);

    parameterUserID.Direction = ParameterDirection.ReturnValue;

    myCommand.Parameters.Add(parameterUserID);

    try

    {   ///打开数据库的连接

        myConnection.Open();

    }

    catch(Exception ex){throw new Exception("数据库连接失败!",ex);}

    try

    {   ///执行数据库的存储过程(访问数据库)

        myCommand.ExecuteNonQuery();

    }

    catch(Exception ex){throw new Exception(ex.Message,ex);}

    finally

    {

        if(myConnection.State == ConnectionState.Open)

        {   ///关闭数据库的连接

            myConnection.Close();

        }

    }

    return (int)parameterUserID.Value;

}

 6.3.3  用户注册页面设计

用户注册功能由Register.aspx页面实现。该页面为用户提供了输入用户名称、用户密码、确认密码、验证码、提交用户注册信息等功能。Register.aspx页面添加了4个TextBox控件和2个Button控件。

下述程序代码声明了1个TextBox控件,用来输入用户名称,ID属性的值为tbUsername。该控件使用了1个TextBoxWatermarkExtender控件和3个ValidatorCalloutExtender控件,它们的ID属性的值分别为wmeName、vceNameBlank、vceNameValue和vceRevName。其中,wmeName控件为tbUsername控件显示水印值“请输入用户名称”;vceNameBlank、vceNameValue和vceRevName控件分别以提示样式显示验证结果。

另外,tbUsername控件使用2个RequiredFieldValidator控件和1个RegularExpressionValidator控件,它们的ID属性的值分别为rfNameBlank、rfNameValue和revName。其中,rfNameBlank控件验证tbName控件的内容不能为空,即用户输入的名称不能为空;rfNameValue控件验证tbName控件的内容不能等于“请输入用户名称”(wmeName水印控件的水印值),这样可以防止用户不输入任何名称就注册;revName控件验证tbUsername控件内容的最小长度为1、最大长度为50。

<!-- 以下HTML代码用来实现输入用户名称的功能 -->

用户名称:<asp:TextBox ID="tbUsername" runat="server" SkinID="tbSkin"

    Width="60%" MaxLength="50"></asp:TextBox>

<asp:RequiredFieldValidator ID="rfNameBlank" runat="server"

    ControlToValidate="tbUsername" Display="none"

    ErrorMessage="用户名称不能为空!"></asp:RequiredFieldValidator>

<asp:RequiredFieldValidator ID="rfNameValue" runat="server"

    ControlToValidate="tbUsername" Display="none"

    InitialValue="请输入用户名称"

    ErrorMessage="用户名称不能为空!"></asp:RequiredFieldValidator>

<asp:RegularExpressionValidator ID="revName" runat="server"

    ControlToValidate="tbUsername" Display="none"

    ErrorMessage="用户名称的长度最大为50,请重新输入。"

    ValidationExpression=".{1,50}">

    </asp:RegularExpressionValidator>

<ajaxToolkit:TextBoxWatermarkExtender ID="wmeName" runat="server"

    TargetControlID="tbUsername" WatermarkText="请输入用户名称"

    WatermarkCssClass="Watermark">

    </ajaxToolkit:TextBoxWatermarkExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameBlank"

    runat="server" TargetControlID="rfNameBlank"

    HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameValue"

    runat="server" TargetControlID="rfNameValue"

    HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameRegex"

    runat="server" TargetControlID="revName"

    HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

在下述程序代码中,btnCheck控件检测用户输入的名称是否存在,并在lbCheckResult控件中显示检测的结果。

<asp:Button ID="btnCheck" runat="server" Text="检查是否重名"

    CausesValidation="False" OnClick="btnCheck_Click"

    SkinID="btnSkin" />

<asp:Label ID="lbCheckResult" runat="server"

    ForeColor="Red"></asp:Label>

在下述程序代码中,btnRegister控件将用户的注册信息提交到数据库的User表中,并在lbMessage控件中显示注册的结果。

<asp:Button ID="btnRegister" runat="server" Text="注册"

    OnClick="btnRegister_Click" Width="80px" SkinID="btnSkin" />

<asp:Label ID="lbMessage" runat="server" CssClass="Text"

    ForeColor="Red"></asp:Label>

综上所述,Register.aspx页面的设计界面如图6.10所示。

Register.aspx页面的完整HTML设计代码(不包括简单的HTML元素,如<table>、<tr>等)如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Register.aspx.cs"

    Inherits="Register" StylesheetTheme="ASPNETAjaxWeb" %>

<head runat="server"><title>用户注册</title></head>

<body><form id="form1" runat="server">

图6.10  用户注册页面Register.aspx的设计界面

    <asp:ScriptManager ID="sm" runat="server" />

    <asp:UpdatePanel ID="up" runat="server"><ContentTemplate>

        <!-- 以下HTML代码用来实现输入用户名称的功能 -->

        用户名称:<asp:TextBox ID="tbUsername" runat="server" SkinID="tbSkin"

            Width="60%" MaxLength="50"></asp:TextBox>

        <asp:Button ID="btnCheck" runat="server" Text="检查是否重名"

            CausesValidation="False" OnClick="btnCheck_Click"

            SkinID="btnSkin" />

        <asp:Label ID="lbCheckResult" runat="server"

            ForeColor="Red"></asp:Label>

        <asp:RequiredFieldValidator ID="rfNameBlank" runat="server"

            ControlToValidate="tbUsername" Display="none"

            ErrorMessage="用户名称不能为空!"></asp:RequiredFieldValidator>

        <asp:RequiredFieldValidator ID="rfNameValue" runat="server"

            ControlToValidate="tbUsername" Display="none"

            InitialValue="请输入用户名称"

            ErrorMessage="用户名称不能为空!"></asp:RequiredFieldValidator>

        <asp:RegularExpressionValidator ID="revName" runat="server"

            ControlToValidate="tbUsername" Display="none"

            ErrorMessage="用户名称的长度最大为50,请重新输入。"

            ValidationExpression=".{1,50}">

            </asp:RegularExpressionValidator>

        <ajaxToolkit:TextBoxWatermarkExtender ID="wmeName" runat="server"

            TargetControlID="tbUsername" WatermarkText="请输入用户名称"

            WatermarkCssClass="Watermark">

            </ajaxToolkit:TextBoxWatermarkExtender>

        <ajaxToolkit:ValidatorCalloutExtender ID="vceNameBlank"

            runat="server" TargetControlID="rfNameBlank"

            HighlightCssClass="Validator">

            </ajaxToolkit:ValidatorCalloutExtender>

        <ajaxToolkit:ValidatorCalloutExtender ID="vceNameValue"

            runat="server" TargetControlID="rfNameValue"

            HighlightCssClass="Validator">

            </ajaxToolkit:ValidatorCalloutExtender>

        <ajaxToolkit:ValidatorCalloutExtender ID="vceNameRegex"

            runat="server" TargetControlID="revName"

            HighlightCssClass="Validator">

            </ajaxToolkit:ValidatorCalloutExtender>

        <!-- 以下HTML代码用来实现输入用户密码的功能 -->

        用户密码:<asp:TextBox ID="tbPassword" runat="server" SkinID="tbSkin"

            Width="60%" MaxLength="50" TextMode="Password">

            </asp:TextBox><br />

        <asp:Label ID="lbHelp" runat="server"></asp:Label>

        <asp:RequiredFieldValidator ID="rfPwdBlank" runat="server"

            ControlToValidate="tbPassword" Display="none"

            ErrorMessage="用户密码不能为空!"></asp:RequiredFieldValidator>

        <ajaxToolkit:ValidatorCalloutExtender ID="vcePwdBlank"

            runat="server" TargetControlID="rfPwdBlank"

            HighlightCssClass="Validator">

            </ajaxToolkit:ValidatorCalloutExtender>

        <ajaxToolkit:PasswordStrength ID="psPassword" runat="server"

            TargetControlID="tbPassword" DisplayPosition="RightSide"

            TextCssClass="PasswordStrengthText"

            HelpHandlePosition="BelowLeft" HelpStatusLabelID="lbHelp"

            MinimumNumericCharacters="2" MinimumSymbolCharacters="2"

            PreferredPasswordLength="10"

            RequiresUpperAndLowerCaseCharacters="true"

            StrengthIndicatorType="Text"

            TextStrengthDescriptions="很差;差;一般;好;很好"

            CalculationWeightings="40;20;20;20">

            </ajaxToolkit:PasswordStrength>

        <!-- 以下HTML代码用来实现输入确认密码的功能 -->

        确认密码:<asp:TextBox ID="tbPasswordStr" runat="server"

            SkinID="tbSkin" Width="60%" MaxLength="50"

            TextMode="Password"></asp:TextBox>

        <asp:CompareValidator ID="cvPwd" runat="server"

            ControlToValidate="tbPassword"

            ControlToCompare="tbPasswordStr" Display="none"

            Operator="Equal" ErrorMessage="两次输入的密码不相同,请重新输入。">

            </asp:CompareValidator>

        <ajaxToolkit:ValidatorCalloutExtender ID="vcePassword"

            runat="server" TargetControlID="cvPwd"

            HighlightCssClass="Validator">

            </ajaxToolkit:ValidatorCalloutExtender>

        <!-- 以下HTML代码用来实现输入验证码的功能 -->

        验 证 码:<asp:TextBox ID="tbCode" runat="server" SkinID="tbSkin"

            Width="80px"></asp:TextBox>

        <asp:Image ID="imgCode" runat="server"

            ImageUrl = "~/ValidateCode.aspx" />

        <!-- 以下HTML代码用来实现提交用户信息的功能 -->

        <asp:Button ID="btnRegister" runat="server" Text="注册"

            OnClick="btnRegister_Click" Width="80px" SkinID="btnSkin" />

        <asp:Label ID="lbMessage" runat="server" CssClass="Text"

            ForeColor="Red"></asp:Label>

    </ContentTemplate></asp:UpdatePanel>

</form></body>

 6.3.4  密码强度提示

在下述程序代码中,tbPassword控件使用PasswordStrength控件提示用户输入密码的强度,包括5个等级:“很差”、“差”、“一般”、“好”和“很好”。其中,“很好”等级密码的最小长度为10,至少包含2个数字,至少包含2个特殊字符,区分英文字母的大小写形式。

<!-- 以下HTML代码用来实现输入用户密码的功能 -->

用户密码:<asp:TextBox ID="tbPassword" runat="server" SkinID="tbSkin"

    Width="60%" MaxLength="50" TextMode="Password">

    </asp:TextBox><br />

<asp:Label ID="lbHelp" runat="server"></asp:Label>

<asp:RequiredFieldValidator ID="rfPwdBlank" runat="server"

    ControlToValidate="tbPassword" Display="none"

    ErrorMessage="用户密码不能为空!"></asp:RequiredFieldValidator>

<ajaxToolkit:ValidatorCalloutExtender ID="vcePwdBlank"

    runat="server" TargetControlID="rfPwdBlank"

    HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:PasswordStrength ID="psPassword" runat="server"

    TargetControlID="tbPassword" DisplayPosition="RightSide"

    TextCssClass="PasswordStrengthText"

    HelpHandlePosition="BelowLeft" HelpStatusLabelID="lbHelp"

    MinimumNumericCharacters="2" MinimumSymbolCharacters="2"

    PreferredPasswordLength="10"

    RequiresUpperAndLowerCaseCharacters="true"

    StrengthIndicatorType="Text"

    TextStrengthDescriptions="很差;差;一般;好;很好"

    CalculationWeightings="40;20;20;20">

    </ajaxToolkit:PasswordStrength>

Register.aspx页面运行之后,如果用户在【用户密码】输入框中输入密码,则页面将动态显示该密码的强度和提示信息,如图6.11所示。

图6.11  密码强度提示

 6.3.5  检测用户名称是否已注册

用户单击Register.aspx页面上的【检查是否重名】按钮,可以检测用户名称是否已经注册。该功能由Register.aspx页面的btnCheck控件的btnCheck_Click(object sender,EventArgs e)事件实现。

btnCheck_Click(object sender,EventArgs e)事件定义在代码隐藏文件Register.aspx.cs中。该文件引入了两个新的命名空间:ASPNETAJAXWeb.ValidateCode.Page和ASPNETAJAXWeb. AjaxUser。程序代码如下:

///引入新的命名空间

using ASPNETAJAXWeb.ValidateCode.Page;

using ASPNETAJAXWeb.AjaxUser;

在下述程序代码中,btnCheck_Click(object sender,EventArgs e)事件可以检测用户名称是否已经注册。该事件首先检测用户输入的名称是否为空,如果为空,则提示用户输入名称;如果不为空,将调用UserDAL类的CheckUser(string username)方法从数据库中检测用户输入的名称是否存在,并返回SqlDataReader对象dr。然后根据dr判断该名称是否存在,并在lbCheckResult控件上显示相应的检测结果。

protected void btnCheck_Click(object sender,EventArgs e)

{   ///检查用户名称是否为空

    if(string.IsNullOrEmpty(tbUsername.Text) == true)

    {

        lbCheckResult.Text = "很遗憾,您输入的用户名称为空,不能注册。请重新输入";

        lbCheckResult.ForeColor = System.Drawing.Color.Red;

        return;

    }

    ///检查用户名称是否存在

    UserDAL user = new UserDAL();

    SqlDataReader dr = user.CheckUser(tbUsername.Text);

    if(dr == null)

    {   ///如果不存在,则可以使用

        lbCheckResult.Text = "恭喜您,您选择的用户名称可以使用。";

        lbCheckResult.ForeColor = System.Drawing.Color.Green;

        return;

    }

    if(dr.Read())

    {   ///如果存在,则不能注册

        if(Int32.Parse(dr["UserCount"].ToString()) > 0)

        {

            lbCheckResult.Text

                = "很遗憾,您选择的用户名称已经被使用了。请重新选择";

            lbCheckResult.ForeColor = System.Drawing.Color.Red;

        }

        else

        {   ///如果不存在,则可以使用

            lbCheckResult.Text = "恭喜您,您选择的用户名称可以使用。";

            lbCheckResult.ForeColor = System.Drawing.Color.Green;

        }

    }

    else

    {   ///如果不存在,则可以使用

        lbCheckResult.Text = "恭喜您,您选择的用户名称可以使用。";

        lbCheckResult.ForeColor = System.Drawing.Color.Green;

    }

    dr.Close();

}

 6.3.6  用户注册

用户单击Register.aspx页面上的【注册】按钮将触发btnRegister_Click(object sender, EventArgs e)事件,该事件实现用户注册功能。

在下述程序代码中,btnRegister_Click(object sender,EventArgs e)事件将用户的注册信息插入到数据库的User表中。该事件首先检测用户输入的验证码是否正确,如果不正确,则显示提示验证码错误,并中止事件;如果验证码正确,则调用UserDAL类的AddUser(String username,String password)方法将用户的注册信息插入到数据库的User表中,并返回新插入记录的ID值。最终,在lbMessage控件上显示注册的结果。

protected void btnRegister_Click(object sender,EventArgs e)

{   ///判断是否创建了验证码

    if(Session[ValidateCode.VALIDATECODEKEY] == null) return;

    ///验证验证码是否相等

    if(tbCode.Text != Session[ValidateCode.VALIDATECODEKEY].ToString())

    {

        lbMessage.Text = "验证码输入错误,请重新输入。";

        return;

    }

    ///注册新用户

    UserDAL user = new UserDAL();

    if(user.AddUser(tbUsername.Text,tbPassword.Text) > 0)

    {

        lbMessage.Text = "恭喜您,注册成功!";

    }

    else{lbMessage.Text = "很遗憾,注册失败!";}

}

将Register.aspx页面设置为AjaxUser应用程序的起始页面,并运行该程序,Register.aspx页面的起始界面如图6.12所示。

图6.12  用户注册页面Register.aspx的起始界面

6.4  用户登录和注销

用户登录和注销功能分别由Login.aspx和Logoff.aspx页面实现,它们的代码隐藏文件分别为Login.aspx.cs和Logoff.aspx.cs。其中,这两个页面都保存在AjaxUser应用程序的根目录下。

 6.4.1  数据访问层设计

在用户登录和注销中,它的数据访问层只实现了1个功能:检测用户名称和用户密码是否正确,如果正确,则能够登录,否则不能够登录。该功能由GetUserLogin(string username,string password)方法实现。

GetUserLogin(string username,string password)方法根据用户输入的名称和密码(分别由username和password参数指定)从数据库的User表中检测该记录的ID,如果不存在,则返回空值。声明该方法的程序代码如下:

public SqlDataReader GetUserLogin(string username,string password)

GetUserLogin(string username,string password)方法返回类型为SqlDataReader。它使用Pr_GetUserLogin存储过程根据用户输入的名称和密码从数据库的User表中检测该记录的ID。该存储过程的程序代码如下:

CREATE PROCEDURE Pr_GetUserLogin

(

    @Username varchar(50),

    @Password varchar(255)

)

AS

SELECT ID

FROM [User]

WHERE Username = @Username AND Password = @Password

在下述程序代码中,GetUserLogin(string username,string password)方法根据用户输入的名称和密码从数据库的User表中检测该记录的ID。该方法的具体实现步骤如下:

* 使用连接字符串ConnectionString创建SqlConnection对象con,该对象用来连接数据库。

* 设置执行的存储过程为Pr_GetUserLogin,并设置myCommand对象的执行方式为存储过程。

* 添加存储过程需要的@Username和@Password参数,并进行赋值。

* 执行存储过程Pr_GetUserLogin,并将结果保存到SqlDataReader对象dr中。

* 如果上述操作成功,则返回SqlDataReader对象dr。

public SqlDataReader GetUserLogin(string username,string password)

{   ///定义数据库的Connection 和 Command

    SqlConnection myConnection = new SqlConnection(ConnectionString);

    SqlCommand myCommand = new SqlCommand("Pr_GetUserLogin",myConnection);

    ///定义访问数据库的方式为存储过程

    myCommand.CommandType = CommandType.StoredProcedure;

    ///创建访问数据库的参数

    SqlParameter parameterUserName

        = new SqlParameter("@Username",SqlDbType.VarChar,50);

    parameterUserName.Value = username;

    myCommand.Parameters.Add(parameterUserName);

    SqlParameter parameterPassword

        = new SqlParameter("@Password",SqlDbType.VarChar,255);

    parameterPassword.Value = password;

    myCommand.Parameters.Add(parameterPassword);

    SqlDataReader dr = null;

    try

    {   ///打开数据库的连接

    myConnection.Open();

    }

    catch(Exception ex){throw new Exception("数据库连接失败!",ex);}

    try

    {   ///执行数据库的存储过程(访问数据库)

        dr = myCommand.ExecuteReader(CommandBehavior.CloseConnection);

    }

    catch(Exception ex){throw new Exception(ex.Message,ex);}

    return dr;                 ///返回dr

}

 6.4.2  避免登录时的SQL注入

Pr_GetUserLogin存储过程能够避免用户登录时的SQL注入,这是因为该存储过程使用参数来传入用户的名称和密码。这样,用户输入的名称和密码都被看成一个整体,即当成一个完整的值来处理,而不是把它们的值作为SQL语句的一部分。Pr_GetUserLogin存储过程的完整代码如下:

CREATE PROCEDURE Pr_GetUserLogin

(

    @Username varchar(50),

    @Password varchar(255)

)

AS

SELECT ID

FROM [User]

WHERE Username = @Username AND Password = @Password

如果用户输入的名称和密码分别为“username OR 'a'='a”和“password”,那么在该存储过程中,上述的WHERE语句被解释为如下语句:

WHERE Username = [username OR 'a'='a] AND Password = 'Password'

在上述语句中,Username = [username OR 'a'='a]构成一个完整的赋值表达式。若使用以下SQL语句来获取登录信息(即用户的ID):

SELECT ID FROM [User] WHERE Username = 名称 AND Password = 密码

当用户输入的名称和密码分别为“username OR 'a'='a”和“password”时,上述SQL语句被解释为如下语句:

SELECT ID FROM [User] WHERE Username = 'username OR 'a'='a' AND Password = 'Password'

因为上述SQL语句中存在永真的条件“'a'='a'”,从而导致WHERE子句为真。因此,上述SQL语句实际上不需要任何用户名称和密码就能够登录系统。

 6.4.3  设计用户登录界面

用户登录功能由Login.aspx页面实现。该页面为用户提供了输入名称、密码等功能,同时,它还将用户输入的名称和密码提交到数据库,并判断该名称和密码是否正确。Login.aspx页面添加了3个TextBox控件和1个Button控件。

下述程序代码声明了1个TextBox控件,用来输入用户名称,ID属性的值为tbUsername。该控件使用了1个TextBoxWatermarkExtender控件和3个ValidatorCalloutExtender控件,它们的ID属性的值分别为wmeName、vceNameBlank、vceNameValue和vceNameRegex。其中,wmeName控件为tbUsername控件显示水印值“请输入用户名称”;vceNameBlank、vceNameValue和vceNameRegex控件分别以提示样式显示验证结果。

另外,tbUsername控件使用2个RequiredFieldValidator控件和1个RegularExpressionValidator控件,它们的ID属性的值分别为rfNameBlank、rfNameValue和revName。其中,rfNameBlank控件验证tbUsername控件的内容不能为空,即用户输入的名称不能为空;rfNameValue控件验证tbUsername控件的内容不能等于“请输入用户名称”(wmeName水印控件的水印值),这样可以防止用户不输入任何内容就登录;revName控件验证tbUsername控件内容的最小长度为1、最大长度为50。

<!-- 以下HTML代码用来实现输入用户名称的功能 -->

用户名称:<asp:TextBox ID="tbUsername" runat="server" SkinID="tbSkin"

    Width="60%" MaxLength="50"></asp:TextBox>

<asp:RequiredFieldValidator ID="rfNameBlank" runat="server"

    ControlToValidate="tbUsername" Display="none"

    ErrorMessage="用户名称不能为空!"></asp:RequiredFieldValidator>

<asp:RequiredFieldValidator ID="rfNameValue" runat="server"

    ControlToValidate="tbUsername" Display="none"

    InitialValue="请输入用户名称" ErrorMessage="用户名称不能为空!">

    </asp:RequiredFieldValidator>

<asp:RegularExpressionValidator ID="revName" runat="server"

    ControlToValidate="tbUsername" Display="none"

    ErrorMessage="用户名称的长度最大为50,请重新输入。"

    ValidationExpression=".{1,50}"></asp:RegularExpressionValidator>

<ajaxToolkit:TextBoxWatermarkExtender ID="wmeName" runat="server"

    TargetControlID="tbUsername" WatermarkText="请输入用户名称"

    WatermarkCssClass="Watermark">

    </ajaxToolkit:TextBoxWatermarkExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameBlank" runat="server"

    TargetControlID="rfNameBlank" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameValue" runat="server"

    TargetControlID="rfNameValue" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameRegex" runat="server"

    TargetControlID="revName" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

综上所述,Login.aspx页面的设计界面如图6.13所示。

图6.13  用户登录页面Login.aspx的设计界面

Login. aspx页面的完整HTML设计代码(不包括简单的HTML元素,如<table>、<tr>等)如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs"

    Inherits="Login" StylesheetTheme="ASPNETAjaxWeb" %>

<head runat="server"><title>用户登录</title></head>

<body><form id="form1" runat="server">

<asp:ScriptManager ID="sm" runat="server" />

<!-- 以下HTML代码用来实现输入用户名称的功能 -->

用户名称:<asp:TextBox ID="tbUsername" runat="server" SkinID="tbSkin"

    Width="60%" MaxLength="50"></asp:TextBox>

<asp:RequiredFieldValidator ID="rfNameBlank" runat="server"

    ControlToValidate="tbUsername" Display="none"

    ErrorMessage="用户名称不能为空!"></asp:RequiredFieldValidator>

<asp:RequiredFieldValidator ID="rfNameValue" runat="server"

    ControlToValidate="tbUsername" Display="none"

    InitialValue="请输入用户名称" ErrorMessage="用户名称不能为空!">

    </asp:RequiredFieldValidator>

<asp:RegularExpressionValidator ID="revName" runat="server"

    ControlToValidate="tbUsername" Display="none"

    ErrorMessage="用户名称的长度最大为50,请重新输入。"

    ValidationExpression=".{1,50}"></asp:RegularExpressionValidator>

<ajaxToolkit:TextBoxWatermarkExtender ID="wmeName" runat="server"

    TargetControlID="tbUsername" WatermarkText="请输入用户名称"

    WatermarkCssClass="Watermark">

    </ajaxToolkit:TextBoxWatermarkExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameBlank" runat="server"

    TargetControlID="rfNameBlank" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameValue" runat="server"

    TargetControlID="rfNameValue" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vceNameRegex" runat="server"

    TargetControlID="revName" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<!-- 以下HTML代码用来实现输入用户密码的功能 -->

用户密码:<asp:TextBox ID="tbPassword" runat="server" SkinID="tbSkin"

    Width="60%" MaxLength="50"></asp:TextBox>

<asp:RequiredFieldValidator ID="rfPwdBlank" runat="server"

    ControlToValidate="tbPassword" Display="none"

    ErrorMessage="用户密码不能为空!"></asp:RequiredFieldValidator>

<asp:RequiredFieldValidator ID="rfPwdValue" runat="server"

    ControlToValidate="tbPassword" Display="none"

    InitialValue="请输入用户密码" ErrorMessage="用户密码不能为空!">

    </asp:RequiredFieldValidator>

<ajaxToolkit:TextBoxWatermarkExtender ID="twePwd" runat="server"

    TargetControlID="tbPassword" WatermarkText="请输入用户密码"

    WatermarkCssClass="Watermark">

    </ajaxToolkit:TextBoxWatermarkExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vcePwdBlank" runat="server"

    TargetControlID="rfPwdBlank" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<ajaxToolkit:ValidatorCalloutExtender ID="vcePwdValue" runat="server"

    TargetControlID="rfPwdValue" HighlightCssClass="Validator">

    </ajaxToolkit:ValidatorCalloutExtender>

<!-- 以下HTML代码用来实现输入验证码的功能 -->

验 证 码:<asp:TextBox ID="tbCode" runat="server" SkinID="tbSkin"

    Width="80px"></asp:TextBox>

<asp:Image ID="imgCode" runat="server" ImageUrl = "~/ValidateCode.aspx" />

<asp:Label ID="lbMessage" runat="server" CssClass="Text"

    ForeColor="Red"></asp:Label>

<asp:Button ID="btnLogin" runat="server" Text="登录"

    OnClick="btnLogin_Click" Width="80px" />

</form></body>

 6.4.4  用户登录

单击Login.aspx页面上的【登录】按钮将触发btnLogin_Click(object sender,EventArgs e)事件,该事件实现用户登录功能。

在下述程序代码中,btnLogin_Click(object sender,EventArgs e)事件将根据用户输入的名称和密码获取该记录的ID值。该事件首先检测用户输入的验证码是否正确,如果不正确,则显示提示验证码错误,并中止事件;如果验证码正确,则调用UserDAL类的GetUserLogin(string username,string password)方法根据用户输入的名称和密码获取该记录的ID值,并返回获取的ID值。最后,在网页上显示用户登录的结果。

protected void btnLogin_Click(object sender,EventArgs e)

{   ///判断是否创建了验证码

    if(Session[ValidateCode.VALIDATECODEKEY] == null) return;

    ///验证验证码是否相等

    if(tbCode.Text != Session[ValidateCode.VALIDATECODEKEY].ToString())

    {

        lbMessage.Text = "验证码输入错误,请重新输入。";

        return;

    }

    ///判断用户的名称和密码是否正确

    UserDAL user = new UserDAL();

    SqlDataReader dr = user.GetUserLogin(tbUsername.Text,tbPassword.Text);

    if(dr == null) return;

    if(dr.Read())

    {   ///用户登录成功

        Session["UserInfo"] = dr["ID"].ToString();

        Response.Write("用户登录成功!");

    }

    else

    {   ///用户登录失败

        Response.Write("用户登录失败!");

    }

    dr.Close();

    Response.End();   ///中止网页输出

}

将Login.aspx页面设置为AjaxUser应用程序的起始页面,并运行该程序,Login.aspx页面的初始界面如图6.14所示。

图6.14  用户登录页面Login.aspx的起始页面

 6.4.5  用户注销

用户注销功能由Logoff.aspx页面实现,它的代码隐藏文件为Logoff.aspx.cs。该页面在其代码隐藏文件的Page_Load(object sender,EventArgs e)事件中实现用户注销功能。

在下述程序代码中,Page_Load(object sender,EventArgs e)事件首先判断保存在Session对象中的用户信息(由关键字“UserInfo”标识)是否为空。如果不为空,则清空该内容,并停止当前Session,最后重定向到登录页面Default.aspx。

protected void Page_Load(object sender, EventArgs e)

{

    if(Session["UserInfo"] != null)

    {   ///清空用户登录信息

        Session["UserInfo"] = null;

        Session.Clear();

        Session.Abandon();                     ///取消当前Session

    }

    Response.Redirect("~/Default.aspx");   ///重定向到登录页面

}

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论