### 设计可以选择保留时间的用户登录

在网站的登录模块中，经常看到除了输入用户名、密码之外，还可以选择“下次自动登录”、“保存密码”等选项。其实，这些选项的作用就是把登录信息保留在本地计算机上，这样用户再次登录时就免去了输入用户名、密码的操作。

下面在本程序中设计一个用户登录模块，可以选择登录信息（包括用户名和密码）的保留时间。例如，可以选择“不保留”、“保留一星期”或者“保留两星期”。程序运行结果如下。

输入基本登录信息，如用户名、密码、验证码，如图 1 所示。

图 1 输入基本登录信息

选择登录信息的保留时间，如图 2 所示。

图 2 选择保留时间

注意：

如果用户使用另一个用户名和密码登录，系统将删除原来保存在Cookie中的用户名和密码，而保留当前用户的登录信息。

说明：

在IE7.0浏览器中，删除Cookie的步骤是选择“工具”/“Internet选项”，在“常规”选项卡中单击“删除”按钮，在打开的“删除浏览的历史记录”对话框中单击“删除Cookie”按钮删除本地计算机上的Cookie。

#### 设计思路

本程序需要输入的内容有用户名、密码、验证码，并可以选择登录信息的保留时间。那么，这几个关键点之间应用什么样的逻辑才能实现登录信息保留到本地计算机？下面来看一下本程序的逻辑流程图，如图 3 所示。

图 3 逻辑流程图

按照上图中的逻辑流程，首先判断用户输入的用户名和密码，如果均不为空则接着判断输入的验证码是否正确，如果验证码正确则判断 Cookie 对象是否为空，Cookie 对象不为空则清空 Cookie 对象，Cookie 对象为空则连接数据库判断输入的用户名和密码的正确性，如果登录信息正确则将其保存到 Cookie，表示登录成功。如果用户输入的用户名和密码均为空，则判断 Cookie 对象是否为空，如果不为空则表示登录成功，即自动登录无需输入用户名和密码。

#### 关键技术

本程序主要应用 Cookie 对象来保存用户信息。

Cookie 对象用于保存客户端浏览器请求的服务器页面，也可用它存放非敏感性的用户信息，信息保存的时间可以根据用户的需要进行设置。并非所有的浏览器都支持 Cookie，并且数据信息是以文本的形式保存在客户端计算机中。

Cookie 对象的常用属性及说明如表所示。

表 Cookie 对象常用属性及说明

属性 | 说明
Expires | 设定 Cookie 变量的有效时间，默认为 1000 分钟，若设为 0，则可以实时删除 Cookie 变量
Name | 取得 Cookie 变量的名称
Value | 获取或设置 Cookie 变量的内容值
Path | 获取或设置 Cookie 适用于的 URL

下面给出关键代码。例如，将信息保存到 Cookie 对象中，代码如下：

if (ddlSave.SelectedValue == "1")

{ //保留登录信息一个星期

Response.Cookies["user"].Value = txtUserName.Text.Trim();

Response.Cookies["user"].Expires = DateTime.Now.AddDays(7);

Response.Cookies["pwd"].Value = pass;

Response.Cookies["pwd"].Expires = DateTime.Now.AddDays(7);

}

else

{

if (ddlSave.SelectedValue == "2")

{ //保留登录信息两个星期

Response.Cookies["user"].Value = txtUserName.Text.Trim();

Response.Cookies["user"].Expires = DateTime.Now.AddDays(14);

Response.Cookies["pwd"].Value = pass;

Response.Cookies["pwd"].Expires = DateTime.Now.AddDays(14);

}

}

例如，删除 Cookie 对象中的数据，代码如下：

if (Request.Cookies["user"] != null & Request.Cookies["pwd"] != null)

{

//删除保存的用户名

HttpCookie cuser = Request.Cookies["user"];

cuser.Expires = DateTime.Now.AddDays(-1);

Response.Cookies.Add(cuser);

//删除保存的密码

HttpCookie cpwd = Request.Cookies["pwd"];

cpwd.Expires = DateTime.Now.AddDays(-1);

Response.Cookies.Add(cpwd);

}

#### 实现步骤

下面介绍“设计可以选择保留时间的用户登录”实例的实现步骤。

（1）创建一个 Web 窗体，默认名为 Default.aspx。

（2）在该窗体中添加控件，所添加的控件类型、控件名称及说明如表所示。

表 11.2 控件类型、控件名称及说明

控件类型 | 控件名称 | 主要属性 | 说明
标准/TextBox 控件 | txtUserName | 均为默认值 | 用于输入登录名
txtUserpass | TextMode 属性设置为 Password | 用于输入登录密码
txtCode | 均为默认值 | 用于输入验证码
HTML/Image 控件 | imgCode | Alt 属性设置为“看不清，请点击我！” | 用于显示验证码
标准/DropDownList 控件 | ddlSave | 自定义 3 个选项 <asp:ListItem Value="0">不保留</asp:ListItem> <asp:ListItem Value="1">保留一星期</asp:ListItem> <asp:ListItem Value="2">保留两星期</asp:ListItem> | 用于选择保留时间
标准/Button 控件 | btnLog | 均为默认值 | 用于实现登录操作

（3）按照逻辑流程图，在登录按钮 btnLog 的 Click 事件中编写实现代码。这里需要注意一下用户输入的会员密码，由于在用户注册时为了增加保密性，对会员密码进行了 MD5 加密并保存到数据库中，在此也应该将会员密码通过 MD5 加密后在使用 SQL 语句查询。为了防止 SQL 注入式攻击使用了 Parameters 属性以传入参数的方法来设置 SQL 语句。实现代码如下。

protected void btnLog_Click(object sender, EventArgs e)

{

if (txtUserName.Text.Trim() != "" & txtUserpass.Text.Trim() != "")

{

//获取验证码

string code = txtCode.Text;

//判断用户输入的验证码是否正确

if (Request.Cookies["CheckCode"].Value == code)

{

if (Request.Cookies["user"] != null & Request.Cookies["pwd"] != null)

{

//清空 Cookie 对象

HttpCookie cuser = Request.Cookies["user"];

cuser.Expires = DateTime.Now.AddDays(-1);

Response.Cookies.Add(cuser);

HttpCookie cpwd = Request.Cookies["pwd"];

cpwd.Expires = DateTime.Now.AddDays(-1);

Response.Cookies.Add(cpwd);

}

//创建数据库连接

SqlConnection con = new SqlConnection("server=.;database=db_object;uid=sa;pwd=;");

//打开数据库连接

con.Open();

//使用 MD5 加密将用户输入的密码加密

string pass = FormsAuthentication.HashPasswordForStoringInConfigFile(txtUserpass.Text, "MD5");

//创建 SQL 语句，该语句用来查询用户输入的用户名和密码是否正确

string sqlSel = "select count(*) from tb_userInfo where userName=@name and userPass=@pass";

//创建 SqlCommand 对象

SqlCommand com = new SqlCommand(sqlSel, con);

//使用 Parameters 的 add 方法添加参数类型

com.Parameters.Add(new SqlParameter("name", SqlDbType.VarChar, 20));

//设置 Parameters 的参数值

com.Parameters["name"].Value = txtUserName.Text;

com.Parameters.Add(new SqlParameter("pass", SqlDbType.VarChar, 50));

com.Parameters["pass"].Value = pass;

//判断 ExecuteScalar 方法返回的参数是否大于大于表示登录成功并给出提示

if (Convert.ToInt32(com.ExecuteScalar()) > 0)

{

if (ddlSave.SelectedValue == "1")

{ //保留登录信息一个星期

Response.Cookies["user"].Value = txtUserName.Text.Trim();

Response.Cookies["user"].Expires = DateTime.Now.AddDays(7);

Response.Cookies["pwd"].Value = pass;

Response.Cookies["pwd"].Expires = DateTime.Now.AddDays(7);

}

else

{

if (ddlSave.SelectedValue == "2")

{ //保留登录信息两个星期

Response.Cookies["user"].Value = txtUserName.Text.Trim();

Response.Cookies["user"].Expires = DateTime.Now.AddDays(14);

Response.Cookies["pwd"].Value = pass;

Response.Cookies["pwd"].Expires = DateTime.Now.AddDays(14);

}

}

RegisterStartupScript("", "<script>alert('登录成功！')</script>");

//清空文本框

txtCode.Text = txtUserName.Text = "";

}

else

{

RegisterStartupScript("", "<script>alert('用户名或密码错误！')</script>");

}

}

else

{

RegisterStartupScript("", "<script>alert('验证码输入错误！')</script>");

}

}

else

{

//Cookie 对象不为空，说明登录信息已保存到 Cookie

if (Request.Cookies["user"] != null & Request.Cookies["pwd"] != null)

{

RegisterStartupScript("", "<script>alert('登录成功！')</script>");

}

RegisterStartupScript("", "<script>alert('用户名或密码错误！')</script>");

}

}