连接到 SQL Server 的可靠方法是在连接字符串中传递用户名和密码。您可以以不同的方式使用此策略:
您可以提示用户输入用户名和密码(例如,使用 Forms 身份验证),然后在连接字符串中将凭据传递到 SQL Server。提示输入凭据具有几个缺点。它要求 SQL Server 分别识别每个用户。而且,它对于连接池也是低效的,因此会限制可伸缩性。有关 Forms 身份验证的示例,请参见asp">简单 Forms 身份验证。
安全说明 在应用程序中提示用户输入用户名和密码是一种潜在的安全威胁。凭据信息必须从浏览器传输到服务器上,而普通的 HTTP 传输未加密。为了获得最佳安全性,在应用程序中提示用户提供凭据时,应使用安全套接字层 (SSL),它在将信息从浏览器发送到服务器之前,对其进行加密。有关如何实现 SSL 的详细信息,请参见 Microsoft 知识库文章 Q307267HOW TO:Windows 2000 中带有安全套接字层的安全 XML Web services。在连接字符串中动态地传递显式用户名
以下示例显示如何动态地创建连接字符串。假定用户名和密码在文本框中是可用的。用一个函数筛选用户输入,以确保它仅包含预设的字符。
提示 如果您熟悉正则表达式的使用,则可以创建此筛选器的更高效版本。有关详细信息,请参见asp">正则表达式类。' Visual Basic Private Function ValidateInput(ByVal validchars As String, _ ByVal userinput As String) As Boolean Dim c As Char For Each c In userinput If validchars.IndexOf(c) < 0 Then Return False End If Next Return True End Function Private Sub OpenDatabase() Dim vChars As String = _ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz*&%$#!" Dim userid As String Dim password As String If ValidateInput(vChars, UserName.Text) Then userid = UserName.Text Else Throw New System.Exception("Invalid user name.") End If If ValidateInput(vChars, PasswordText.Text) Then password = PasswordText.Text Else Throw New System.Exception("Invalid password.") End If Dim connectionString As String connectionString = "data source=myserver" connectionString &= ";initial catalog=northwind" connectionString &= ";user;password=" & password SqlConnection1.ConnectionString = connectionString SqlConnection1.Open() ' Further code to work with the database End Sub // C# private Boolean ValidateInput(String validchars, String userinput) { foreach(Char c in userinput) { if(validchars.IndexOf(c) < 0) { return false; } } return true; } private void OpenDatabase() { String vChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz*&%$#!"; String userid; String password; if(ValidateInput(vChars, UserName.Text)) { userid = UserName.Text; } else { throw new System.Exception("Invalid user name."); } if(ValidateInput(vChars, PasswordText.Text)) { password = PasswordText.Text; } else { throw new System.Exception("Invalid password."); } String connectionString; connectionString = "data source=myserver"; connectionString += ";initial catalog=northwind"; connectionString += ";user;password=" + password; sqlConnection1.ConnectionString = connectionString; sqlConnection1.Open(); // Further code to work with the database }如果没有提示您输入凭据,则可以使用预设的用户名和密码。推荐的方法是将预设的用户名和密码存储在服务器上,然后在运行时读取它并将它添加到连接字符串。此技术的优点是:您的应用程序可以根据它需要在数据库中执行的操作,在不同情况下使用不同的凭据访问数据库。
安全说明 决不将凭据以字符串形式硬编码到您应用程序的程序中。能够访问代码文件(甚至是已编译的代码)的任何人员,都将能够获取凭据。安全说明 始终将资源的最少访问特权给予预设用户名。决不使用“sa”或任何其他管理级别的用户名。始终使用密码。您可以将凭据存储在各种不同的位置。两个选项是:
如果您确实将凭据作为应用程序的一部分进行存储,则应该尝试通过加密来保护它们。一种可能性是使用“数据保护 API”(DPAPI)。有关详细信息,请参见 MSDN 技术文章“Windows 数据保护”。
在 Web.config 中存储凭据
以下示例说明包含标记为“mappedname”和“mappedkey”的用户名和密码的 <add> 关键字。
提示 在应用程序中最好不使用字符串“password”和“user name”(或“username”),这样,搜索这些词的恶意用户就找不到它们。<appSettings> <add key="mappedname" value="MyWebAppUser"/> <add key="mappedkey" value="Aje$31"/> </appSettings>以下示例显示如何在运行时读取凭据并将它们串联到连接字符串中:
' Visual Basic Dim connectionString As String Dim user As String = System.Configuration.ConfigurationSettings. _ AppSettings("mappedname") Dim pass As String = System.Configuration.ConfigurationSettings. _ AppSettings("mappedkey") connectionString = "data source=myserver;initial catalog=northwind" connectionString &= ";user;password=" & pass SqlConnection1.ConnectionString = connectionString // C# String connectionString; String user = System.Configuration.ConfigurationSettings. AppSettings["mappedname"]; String pass = System.Configuration.ConfigurationSettings. AppSettings["mappedkey"]; connectionString = "data source=myserver;initial catalog=northwind"; connectionString += ";user;password=" + pass; sqlConnection1.ConnectionString = connectionString;在注册表中存储凭据
以下示例说明如何从子项“Connection”中获取用户名和密码(作为名为“mappedname”和“mappedkey”的字符串值存储):
' Visual Basic Dim user, pass, connectionString As String user = Microsoft.Win32.Registry.LocalMachine.OpenSubKey( _ "Software\Connection").GetValue("mappedname").ToString() pass = Microsoft.Win32.Registry.LocalMachine.OpenSubKey( _ "Software\Connection").GetValue("mappedkey").ToString() connectionString = "data source=myserver;initial catalog=northwind" connectionString &= ";user;password=" & pass SqlConnection1.ConnectionString = connectionString // C# String user, pass, connectionString; user = Microsoft.Win32.Registry.LocalMachine. OpenSubKey("Software\\Connection"). GetValue("mappedname").ToString(); pass = Microsoft.Win32.Registry.LocalMachine. OpenSubKey("Software\\Connection"). GetValue("mappedkey").ToString(); connectionString = "data source=myserver;initial catalog=northwind"; connectionString += ";user;password=" + pass; sqlConnection1.ConnectionString = connectionString;