`

如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证

阅读更多
作者:微软
本文的发布号曾为 CHS301240
有关本文的 Microsoft Visual Basic .NET 版本,请参阅 308157

在 Web.config 文件中配置安全设置

本节介绍如何添加和修改 <authentication><authorization> 配置部分,以便将 ASP.NET 应用程序配置为使用基于窗体的身份验证。
1. 在项目资源管理器中,打开 Web.config 文件。
2. 将身份验证模式更改为Forms(窗体)。
3. 插入 <Forms> 标记,并填入相应的属性。(有关这些属性的更多信息,请参阅 参考 一节中列出的 MSDN 文档或快速入门文档。)复制以下代码,然后单击“编辑”菜单上的“粘贴为 HTML”,以粘贴文件 <authentication> 部分中的代码:
<authentication mode="Forms">
   <forms name=".ASPXFORMSDEMO" loginUrl="logon.aspx"
   protection="All" path="/" timeout="30" />
</authentication>
					
4. <authorization> 部分中拒绝匿名用户的访问(如下所示):
<authorization>
   <deny users ="?" />
   <allow users = "*" />
</authorization>
					
返回页首

创建示例数据库表以存储用户详细信息

本节介绍如何创建可存储用户名、密码和用户角色的示例数据库。如果要将用户角色存储在数据库中并实现基于角色的安全性,则需要角色列。
1. 在“开始”菜单上,单击“运行”,然后键入 notepad 以打开记事本。
2. 突出显示以下 SQL 脚本代码,右键单击该代码,然后单击“复制”。在记事本中,单击“编辑”菜单上的“粘贴”以粘贴以下代码:
if exists (select * from sysobjects where id =
object_id(N'[dbo].[Users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Users]
GO
CREATE TABLE [dbo].[Users] (
   [uname] [varchar] (15) NOT NULL ,
   [Pwd] [varchar] (25) NOT NULL ,
   [userRole] [varchar] (25) NOT NULL ,
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Users] WITH NOCHECK ADD
   CONSTRAINT [PK_Users] PRIMARY KEY  NONCLUSTERED
   (
      [uname]
   )  ON [PRIMARY]
GO

INSERT INTO Users values('user1','user1','Manager')
INSERT INTO Users values('user2','user2','Admin')
INSERT INTO Users values('user3','user3','User')
GO
					
3. 将该文件另存为 Users.sql。
4. 在 Microsoft SQL Server 计算机上,在查询分析器中打开 Users.sql。在数据库列表中,单击“pubs”,然后运行该脚本。这将创建一个示例用户表,并使用此示例应用程序填充要使用的 Pubs 数据库中的该表。
返回页首

创建 Logon.aspx 页

1. 将一个新的 Web 窗体添加到名为 Logon.aspx 的项目中。
2. 在编辑器中打开 Logon.aspx 页,并切换到 HTML 视图。
3. 复制以下代码,然后使用“编辑”菜单上的“粘贴为 HTML”选项将代码插入到 <form> 标记之间:
<h3>
   <font face="Verdana">Logon Page</font>
</h3>
<table>
   <tr>
      <td>Email:</td>
      <td><input id="txtUserName" type="text" runat="server"></td>
      <td><ASP:RequiredFieldValidator ControlToValidate="txtUserName"
           Display="Static" ErrorMessage="*" runat="server"
           ID="vUserName" /></td>
   </tr>
   <tr>
      <td>Password:</td>
      <td><input id="txtUserPass" type="password" runat="server"></td>
      <td><ASP:RequiredFieldValidator ControlToValidate="txtUserPass"
          Display="Static" ErrorMessage="*" runat="server"
          ID="vUserPass" />
      </td>
   </tr>
   <tr>
      <td>Persistent Cookie:</td>
      <td><ASP:CheckBox id="chkPersistCookie" runat="server" autopostback="false" /></td>
      <td></td>
   </tr>
</table>
<input type="submit" Value="Logon" runat="server" ID="cmdLogin"><p></p>
<asp:Label id="lblMsg" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat="server" />
						
此 Web 窗体用于向用户提供登录窗体,以便他们提供用于登录到应用程序的用户名和密码。
4. 切换到“设计”视图并保存该页。
返回页首

对事件处理程序进行编码以使它验证用户凭据

本节给出位于代码隐藏页 (Logon.aspx.cs) 中的代码。
1. 双击“Logon”打开 Logon.aspx.cs 文件。
2. 导入代码隐藏文件中必需的命名空间:
using System.Data.SqlClient;
using System.Web.Security;
					
3. 创建 ValidateUser 函数,以便通过查找数据库来验证用户凭据。(确保将连接字符串更改为指向数据库。)
private bool ValidateUser( string userName, string passWord )
{
	SqlConnection conn;
	SqlCommand cmd;
	string lookupPassword = null;

	// Check for invalid userName.
	// userName must not be null and must be between 1 and 15 characters.
	if ( (  null == userName ) || ( 0 == userName.Length ) || ( userName.Length > 15 ) )
	{
		System.Diagnostics.Trace.WriteLine( "[ValidateUser] Input validation of userName failed." );
		return false;
	}

	// Check for invalid passWord.
	// passWord must not be null and must be between 1 and 25 characters.
	if ( (  null == passWord ) || ( 0 == passWord.Length ) || ( passWord.Length > 25 ) )
	{
		System.Diagnostics.Trace.WriteLine( "[ValidateUser] Input validation of passWord failed." );
		return false;
	}

	try
	{
		// Consult with your SQL Server administrator for an appropriate connection
		// string to use to connect to your local SQL Server.
		conn = new SqlConnection( "server=localhost;Integrated Security=SSPI;database=pubs" );
		conn.Open();

		// Create SqlCommand to select pwd field from users table given supplied userName.
		cmd = new SqlCommand( "Select pwd from users where uname=@userName", conn );
		cmd.Parameters.Add( "@userName", SqlDbType.VarChar, 25 );
		cmd.Parameters["@userName"].Value = userName;

		// Execute command and fetch pwd field into lookupPassword string.
		lookupPassword = (string) cmd.ExecuteScalar();

		// Cleanup command and connection objects.
		cmd.Dispose();
		conn.Dispose();
	}
	catch ( Exception ex )
	{
		// Add error handling here for debugging.
		// This error message should not be sent back to the caller.
		System.Diagnostics.Trace.WriteLine( "[ValidateUser] Exception " + ex.Message );
	}

	// If no password found, return false.
	if ( null == lookupPassword )
	{
		// You could write failed login attempts here to event log for additional security.
		return false;
	}

	// Compare lookupPassword and input passWord, using a case-sensitive comparison.
	return ( 0 == string.Compare( lookupPassword, passWord, false ) );

}
					
4. 可使用两种方法之一生成窗体身份验证 Cookie,并将用户重定向到 cmdLogin_ServerClick 事件中的相应页。为两种情形都提供了示例代码。可根据需要使用其中的一个。
调用 RedirectFromLoginPage 方法,以便自动生成窗体身份验证 Cookie,并将用户重定向到 cmdLogin_ServerClick 事件中的相应页:
private void cmdLogin_ServerClick(object sender, System.EventArgs e)
{
if (ValidateUser(txtUserName.Value,txtUserPass.Value) )
	FormsAuthentication.RedirectFromLoginPage(txtUserName.Value,
		chkPersistCookie.Checked);
	else
		Response.Redirect("logon.aspx", true);
}
						
生成身份验证票证,对其进行加密,创建 Cookie,将其添加到响应中并重定向用户。这样,您就可以更好地控制 Cookie 的创建方式了。在本例中还可包括自定义数据和 FormsAuthenticationTicket
private void cmdLogin_ServerClick(object sender, System.EventArgs e)
{
   if (ValidateUser(txtUserName.Value,txtUserPass.Value) )
   {
      FormsAuthenticationTicket tkt;
      string cookiestr;
      HttpCookie ck;
      tkt = new FormsAuthenticationTicket(1, txtUserName.Value, DateTime.Now,
DateTime.Now.AddMinutes(30), chkPersistCookie.Checked, "your custom data");
      cookiestr = FormsAuthentication.Encrypt(tkt);
      ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
      if (chkPersistCookie.Checked)
      ck.Expires=tkt.Expiration;
		    ck.Path = FormsAuthentication.FormsCookiePath;
      Response.Cookies.Add(ck);

      string strRedirect;
      strRedirect = Request["ReturnUrl"];
      if (strRedirect==null)
            strRedirect = "default.aspx";
         Response.Redirect(strRedirect, true);
   }
   else
      Response.Redirect("logon.aspx", true);
}
						
5. 确保将以下代码添加到由 Web 窗体设计器生成的代码的 InitializeComponent 方法中。
this.cmdLogin.ServerClick += new System.EventHandler(this.cmdLogin_ServerClick);
					
返回页首

创建 Default.aspx 页

本节创建一个测试页,用户经过身份验证后将重定向到该页。如果用户在没有先登录到应用程序的情况下浏览此页,则将他们重定向到登录页。
1. 将现有 WebForm1.aspx 页重命名为 Default.aspx,并在编辑器中打开它。
2. 切换到 HTML 视图,并将下面的代码复制到 <form> 标记之间:
<input type="submit" Value="SignOut" runat="server" id="cmdSignOut">
						
此按钮用于注销窗体身份验证会话。
3. 切换到“设计”视图并保存该页。
4. 导入代码隐藏文件中必需的命名空间:
using System.Web.Security;
					
5. 双击 SignOut 打开代码隐藏页 (Default.aspx.cs),并在 cmdSignOut_ServerClick 事件处理程序中复制以下代码:
private void cmdSignOut_ServerClick(object sender, System.EventArgs e)
{
   FormsAuthentication.SignOut();
   Response.Redirect("logon.aspx", true);
}
					
6. 确保将以下代码添加到由 Web 窗体设计器生成的代码的 InitializeComponent 方法中。
this.cmdSignOut.ServerClick += new System.EventHandler(this.cmdSignOut_ServerClick);
					
7. 保存并编译项目。现在,您就可以使用该应用程序了。
返回页首

其他说明

您可能希望将密码安全地存储在数据库中。在将密码存储在数据库或配置文件中之前,可以使用名为 HashPasswordForStoringInConfigFileFormsAuthentication 类实用工具函数对密码进行加密。
您可能希望将 SQL 连接信息存储在配置文件 (Web.config) 中,以便在需要时方便地修改它。
也可以考虑添加代码,以防黑客使用不同的密码组合进行登录。例如,可以包含一个只允许两次或三次登录尝试的逻辑。如果用户在尝试特定次数后无法登录,您可能希望在数据库中设置一个标志以禁止此用户登录,直到此用户通过访问另外一个页面或拨打您的支持电话重新启用其帐户时为止。另外,还应根据需要添加相应的错误处理代码。
因为用户是基于身份验证 Cookie 来标识的,所以您可能希望在此应用程序上使用安全套接字层 (SSL),这样任何人都无法骗取身份验证 Cookie 和传输的任何其他重要信息。
基于窗体的身份验证要求客户机在其浏览器上接受或启用 Cookie。
<authentication> 配置部分的 timeout 参数控制重新生成身份验证 Cookie 的时间间隔。您可以选择一个能提供较好性能和安全性的值。
Internet 上的某些中间代理和缓存可能会将包含“设置 Cookie”标题的 Web 服务器响应缓存起来,然后将其返回给另外一个用户。因为基于窗体身份验证使用 cookie 来验证用户身份,所以这可能导致用户通过接收到由中间代理或缓存提供的本不是要发送给他们的 cookie 而意外(或有意地)模拟另外的用户。下面这篇文章介绍如何对付这些情形:
263730 Site Server 用户可能被验证成错误的帐户
返回页首

参考

有关如何使用 <credentials> 部分存储用户和密码来实现基于窗体的简单身份验证的更多信息,请参阅以下 GotDotNet ASP.NET 快速入门示例: 有关如何使用 XML 文件存储用户和密码来实现基于窗体的身份验证的更多信息,请参阅 .NET Framework 软件开发工具包 (SDK) 文档中的以下主题: 有关 ASP.NET Web 应用程序安全性的更多信息,请参阅以下 Microsoft .NET Framework 开发人员指南文档: 有关 System.Web.Security 命名空间的更多信息,请参阅以下 Microsoft .NET Framework 参考文档: 有关 ASP.NET 配置的更多信息,请参阅以下 Microsoft .NET Framework 开发人员指南文档: 有关 ASP.NET 安全指南的更多信息,请参阅以下 MSDN 白皮书: 有关 ASP.NET 的更多常规信息,请访问以下 MSDN 新闻组: 返回页首

这篇文章中的信息适用于:
Microsoft ASP.NET (included with the .NET Framework 1.1)
Microsoft Visual C# .NET 2003 标准版
Microsoft ASP.NET (included with the .NET Framework) 1.0
Microsoft Visual C# .NET 2002 标准版
Microsoft SQL Server 2000 标准版
Microsoft SQL Server 7.0 标准版
Microsoft SQL Server 2000 64-bit Edition
分享到:
评论

相关推荐

    《asp.net中的窗体身份验证(完整篇之三:用户登录页面)》源代码3

    博文《asp.net中的窗体身份验证(完整篇之三:用户登录页面)》中的源代码之三(http://blog.csdn.net/smallfools/archive/2009/05/28/4222155.aspx)

    ASP.NET使用身份验证创建登录窗体

    ASP.NET使用身份验证创建登录窗体 包括题目和程序 对初级学者还是有用 我这还有蛮多 好的话我再上传

    《asp.net中的窗体身份验证(完整篇之五:不同的角色访问不同的目录)》源代码

    博文《asp.net中的窗体身份验证(完整篇之五:不同的角色访问不同的目录》中的源代码

    ASP.NET MVC:窗体身份验证及角色权限管理示例

    ASP.NET MVC:窗体身份验证及角色权限管理示例

    asp.net知识库

    在ASP.NET中使用WINDOWS验证方式连接SQL SERVER数据库 改进ADO.Net数据库访问方式 ASP.NET 2.0 绑定高级技巧 简单实用的DataSet更新数据库的类+总结 [ADO.NET]由数据库触发器引发的问题 为ASP.NET封装的SQL数据库...

    《asp.net中的窗体身份验证(完整篇之三:用户登录页面)》源代码1

    博文《asp.net中的窗体身份验证(完整篇之三:用户登录页面)》中的源代码之一(http://blog.csdn.net/smallfools/archive/2009/05/28/4222155.aspx)

    ASP.NET常见问题集锦.zip

    在ASP.NET程序中实现上传下载文件.doc 复合 Web 控件示例(2.0).doc 如何在ASP.Net中把图片存入数据库.txt 如何在DateTime字段里只存储日期部分?.txt 如何用.NET创建Windows服务.doc 委托与事件.doc 学生...

    ASP.NET4高级程序设计第4版 带目录PDF 分卷压缩包 part1

    ASP.NET 4高级程序设计(第4版)》【原版书为:Pro ASP.NET 4 in C# 2010】是ASP.NET领域的鸿篇巨制,全面讲解了ASP.NET4的各种特性及其背后的工作原理,并给出了许多针对如何构建复杂、可扩展的网站从实践中得出的...

    asp.net中的窗体身份验证(最简单篇)

    在创建网站中,常常会使用到身份验证。asp.net中内置了几种身份验证的方式,如Windows、Froms、Passport等。这几种身份验证的方式各有不同。一般来说,网站的身份验证方式都会经过以下几个步骤: 1、输入用户名和...

    ASP.NET 3.5 开发大全

    第二篇 ASP.NET窗体控件 第5章 Web窗体的基本控件 5.1 控件的属性 5.2 简单控件 5.2.1 标签控件(Label) 5.2.2 超链接控件(HyperLink) 5.2.3 图像控件(Image) 5.3 文本框控件(TextBox) 5.3.1 文本框控件的...

    ASP.NET 3.5 开发大全word课件

    第二篇 ASP.NET窗体控件 第5章 Web窗体的基本控件 5.1 控件的属性 5.2 简单控件 5.2.1 标签控件(Label) 5.2.2 超链接控件(HyperLink) 5.2.3 图像控件(Image) 5.3 文本框控件(TextBox) 5.3.1 文本框控件的...

    ASP.NET3.5从入门到精通

    第二篇 ASP.NET窗体控件 第 5 章 Web 窗体的基本控件 5.1 控件的属性 5.2 简单控件 5.2.1 标签控件(Label) 5.2.2 超链接控件(HyperLink) 5.2.3 图像控件(Image) 5.3 文本框控件(TextBox) 5.3.1 文本框控件的...

    ASP.NET教学讲义,完整章节

    1.2.3 ASP.NET应用程序示例 23 第二章:WEB服务器控件 26 2.1 WEB 服务器控件的格式 26 2.2 服务器控件的类型 27 2.3 用服务器控件建立页面 27 2.4 控件的常见属性 29 2.5 控件的种类 31 第三章:HTML控件和验证控件...

    ASP.NET 3.5 开发大全1-5

    第二篇 ASP.NET窗体控件 第5章 Web窗体的基本控件 5.1 控件的属性 5.2 简单控件 5.2.1 标签控件(Label) 5.2.2 超链接控件(HyperLink) 5.2.3 图像控件(Image) 5.3 文本框控件(TextBox) 5.3.1 文本框控件的...

    2.ASP.NET.2.0.高级编程(第4版) [1/7]

    书中提供了大量的实例,可帮助读者快速掌握如何在.NET平台下开发功能强大的ASP.NET应用程序。本书适合有一些基础的ASP.NET初级程序员以及准备迁移到ASP.NET 2.0的编程老手。该书与《ASP.NET 2.0入门经典(第4版)》...

    ASP.NET 3.5 开发大全11-15

    第二篇 ASP.NET窗体控件 第5章 Web窗体的基本控件 5.1 控件的属性 5.2 简单控件 5.2.1 标签控件(Label) 5.2.2 超链接控件(HyperLink) 5.2.3 图像控件(Image) 5.3 文本框控件(TextBox) 5.3.1 文本框控件的...

Global site tag (gtag.js) - Google Analytics