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

文章翻译 文章翻译
文章编号: 308157 - 查看本文应用于的产品
本文的发布号曾为 CHS308157
展开全部 | 关闭全部

本文内容

概要

本文介绍如何通过使用数据库存储用户来实现基于窗体的身份验证。

要求

下表列出了推荐使用的硬件、软件、网络架构以及所需的 Service Pack:
  • Microsoft Visual Studio .NET
  • Microsoft SQL Server
  • Microsoft Internet 信息服务 (IIS) 5.0 或更高版本

使用 Visual Basic .NET 创建 ASP.NET 应用程序

  1. 打开 Visual Studio .NET。
  2. 新建 ASP.NET Web 应用程序,并指定应用程序的名称和位置。

在 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. 从 Windows 开始菜单中,单击运行,然后键入 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.vb) 中的代码。
  1. 打开 Logon.aspx.vb 文件。
  2. 导入代码隐藏文件中必需的命名空间:
    Imports System.Data.SqlClient
    Imports System.Web.Security
    					
  3. 创建 ValidateUser 函数,以便通过查找数据库来验证用户凭据。(确保将 Connection 字符串更改为指向数据库。)
    Private Function ValidateUser(ByVal userName As String, ByVal passWord As String) As Boolean
            Dim conn As SqlConnection
            Dim cmd As SqlCommand
            Dim lookupPassword As String
    
            lookupPassword = Nothing
    
            ' Check for an invalid userName.
            ' userName  must not be set to nothing and must be between one and 15 characters.
            If ((userName Is Nothing)) Then
                System.Diagnostics.Trace.WriteLine("[ValidateUser] Input validation of userName failed.")
                Return False
            End If
            If ((userName.Length = 0) Or (userName.Length > 15)) Then
                System.Diagnostics.Trace.WriteLine("[ValidateUser] Input validation of userName failed.")
                Return False
            End If
    
            ' Check for invalid passWord.
            ' passWord must not be set to nothing and must be between one and 25 characters.
            If (passWord Is Nothing) Then
                System.Diagnostics.Trace.WriteLine("[ValidateUser] Input validation of passWord failed.")
                Return False
            End If
            If ((passWord.Length = 0) Or (passWord.Length > 25)) Then
                System.Diagnostics.Trace.WriteLine("[ValidateUser] Input validation of passWord failed.")
                Return False
            End If
    
            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 the users table given a 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 = cmd.ExecuteScalar()
    
                ' Cleanup command and connection objects.
                cmd.Dispose()
                conn.Dispose()
            Catch ex As Exception
                ' 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)
            End Try
    
            ' If no password found, return false.
            If (lookupPassword Is Nothing) Then
                ' You could write failed login attempts here to the event log for additional security.
                Return False
            End If
    
            ' Compare lookupPassword and input passWord by using a case-sensitive comparison.
            Return (String.Compare(lookupPassword, passWord, False) = 0)
    
    End Function
    					
  4. 可使用两种方法之一生成窗体身份验证 Cookie,并将用户重定向到 cmdLogin_ServerClick 事件中的相应页。为两种情形都提供了示例代码。可根据需要使用其中的一个。
    • 调用 RedirectFromLoginPage 方法,以便自动生成窗体身份验证 Cookie,并将用户重定向到 cmdLogin_ServerClick 事件中的相应页:
      Private Sub cmdLogin_ServerClick(ByVal sender As Object, ByVal e As System.EventArgs) _
         Handles cmdLogin.ServerClick
         If ValidateUser(txtUserName.Value,txtUserPass.value) Then
            FormsAuthentication.RedirectFromLoginPage(txtUserName.Value, _
            chkPersistCookie.Checked)
         Else
            Response.Redirect("logon.aspx", True)
         End If
      End Sub
      						
    • 生成身份验证票证,对其进行加密,创建 Cookie,将其添加到响应中并重定向用户。这样,您就可以更好地控制 Cookie 的创建方式了。在本例中还可以包括自定义数据和 FormsAuthenticationTicket
      Private Sub cmdLogin_ServerClick(ByVal sender As Object, _
         ByVal e As System.EventArgs) Handles cmdLogin.ServerClick
         If Validateuser(txtUserName.Value,txtUserPass.Value) Then
            Dim tkt As FormsAuthenticationTicket
            Dim cookiestr As String
            Dim ck As HttpCookie
      
            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) then ck.Expires=tkt.Expiration 
            ck.Path = FormsAuthentication.FormsCookiePath() 
            Response.Cookies.Add(ck)
      
            Dim strRedirect As String
            strRedirect = Request("ReturnURL")
            If strRedirect <> "" Then
               Response.Redirect(strRedirect, True)
            Else
               strRedirect = "default.aspx"
               Response.Redirect(strRedirect, True)
            End If
         Else
            Response.Redirect("logon.aspx", True)
         End If
      End Sub
      						

创建 Default.aspx 页

本节创建一个测试页,用户经过身份验证后将重定向到该页。如果用户在没有先登录到应用程序的情况下浏览此页,则将他们重定向到登录页。
  1. 将现有 WebForm1.aspx 页重命名为 Default.aspx,并在编辑器中打开它。
  2. 切换到 HTML 视图,并将下面的代码复制到 <form> 标记之间:
    <input type="submit" Value="SignOut" runat="server" id="cmdSignOut">
    						
    此按钮用于注销窗体身份验证会话。
  3. 切换到“设计”视图并保存该页。
  4. 导入代码隐藏文件中必需的命名空间:
    Imports System.Web.Security
    					
  5. 打开代码隐藏页 (Default.aspx.vb),并将以下代码复制到 cmdSignOut_ServerClick 事件处理程序中:
    Private Sub cmdSignOut_ServerClick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles cmdSignOut.ServerClick
       FormsAuthentication.SignOut()
       Response.Redirect("logon.aspx", True)
    End Sub
    					
  6. 保存并编译项目。现在,您就可以使用该应用程序了。

疑难解答

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

参考

有关使用 <credentials> 部分存储用户和密码以实现简单的、基于窗体的身份验证的信息,请参阅 ASP.NET 快速入门示例中的以下文章:
基于窗体的身份验证
http://quickstarts.asp.net/QuickStartv20/aspnet/doc/security/formsauth.aspx
有关使用扩展标记语言 (XML) 文件存储用户和密码来实现基于窗体的身份验证的信息,请参阅 .NET Framework 软件开发工具包 (SDK) 文档中的以下主题:
使用 XML 用户文件的窗体身份验证
http://msdn.microsoft.com/en-us/library/1b1y85bh(vs.71).aspx
有关 ASP.NET Web 应用程序安全性的更多信息,请参见 .NET Framework SDK 文档中的以下文章:
ASP.NET Web 应用程序安全性
http://msdn.microsoft.com/en-us/library/330a99hc(vs.71).aspx
有关 System.Web.Security 命名空间的更多信息,请参见 .NET Framework SDK 文档中的以下文章:
http://msdn.microsoft.com/library/dotnet/cpref/frlrfsystemwebsecurity.htm
有关 ASP.NET 配置的更多信息,请参见以下 .NET Framework SDK 文章:
ASP.NET 配置
http://msdn.microsoft.com/en-us/library/aa719558(VS.71).aspx

ASP.NET 配置部分
http://msdn.microsoft.com/en-us/library/w7w4sb0w(vs.71).aspx
有关 ASP.NET 安全指南的更多信息,请参见以下 MSDN 白皮书:
ASP.NET 中的身份验证:.NET 安全指南
http://msdn.microsoft.com/en-us/library/ms978378.aspx
有关 ASP.NET 的更多常规信息,请访问以下 MSDN 新闻组:
microsoft.public.dotnet.framework.aspnet
有关更多信息,请参见下列书籍:
Esposito、Dino。使用 ASP.NET 和 ADO.NET 构建 Web 解决方案. Microsoft Press, 2001。

属性

文章编号: 308157 - 最后修改: 2012年6月29日 - 修订: 9.0
这篇文章中的信息适用于:
  • Microsoft ASP.NET 1.1
  • Microsoft ASP.NET 1.0
  • Microsoft Visual Basic .NET 2003 标准版
  • Microsoft Visual .NET 2002 标准版
  • Microsoft SQL Server 2000 标准版
  • Microsoft SQL Server 7.0 标准版
关键字:?
kbproductlink kbconfig kbhowtomaster kbsecurity kbweb KB308157
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com