如何指定強式的 SA 密碼,當您安裝 SQL Server 2000 桌面引擎 (MSDE 2000)

文章翻譯 文章翻譯
文章編號: 814463 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

結論

本文說明如何指定增強式 sa 密碼,當您安裝 SQL Server 桌面引擎 (也稱為 MSDE 2000)。

其他相關資訊

SQL Server 2000 桌面引擎 (MSDE 2000) 的任何執行個體安裝期間,您必須將強式密碼指派給 sa 帳戶中。如果即使該執行個體使用 Windows 驗證模式必須這麼做。sa 帳戶無法使用由任何使用者,在 Windows 驗證模式中執行時 ; 不過,執行個體可以稍後切換到混合模式而 sa 帳戶會變成作用中的登入。

如果 sa 帳戶有 Null 值,空白、 簡單,或已知的密碼時的 MSDE 2000 執行個體切換為混合模式,MSDE 執行個體可以再存取未經授權的使用者。sa 帳戶無法卸除,而且它必須總是保護以強式密碼來協助限制未授權的存取。任何使用 sa] 帳戶取得存取權的 MSDE 2000 執行個體的使用者可能會取得完整控制權的 MSDE,該執行個體上,而且有能夠存取 MSDE 服務帳戶具有的任何資源。根據預設,MSDE 服務帳戶是 LocalSystem 內建的安全性帳戶。

如需有關增強式密碼的詳細資訊,請造訪下列 Microsoft 網站]:

Security Rules

您可以使用自訂應用程式的程式碼來安裝 MSDE。 應用程式的程式碼必須使用其中一個下列兩種方法來設定 sa 密碼:
  • 如果使用者是要設定 MSDE 在混合模式下,並會將使用 sa 帳戶,請向使用者要求增強式 sa 帳戶密碼。使用該密碼中將 MSDE 安裝程式。
  • 如果沒有使用 sa 帳戶則產生隨機字串,,然後將該字串為 sa 密碼給 MSDE 安裝程式。

若要協助改善安全性,不應該硬式編碼在安裝程式以在 Setup.ini 檔案中的參數或命令提示字元指派的 sa 密碼切換命令 (.cmd) 檔案中或包含為屬性 MSI 檔案中] 或 [以任何其他可以公開為純文字密碼的方式。密碼應該由動態地產生應用程式安裝程式在執行階段而它應該會傳遞至 MSDE 安裝程序下列方式之一:
  • 從應用程式安裝程式碼執行 MSDE setup.exe,然後在引數中指定 SAPWD 值。

    比方說使用.NET Framework 處理程序] 類別來執行安裝程式並再指定 SAPWD ProcessStartInfo 引數] 屬性中或使用 Win32 CreateProcess] 函數執行安裝程式,然後指定 SAPWD lpCommandLine 參數中。


    如 SAPWD 命令列參數的更多有關,按一下 [下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
    810826新變數 MSDE 服務套件 2 安裝程式中的選項
  • 執行自訂動作,在傳遞強性密碼,當您在自訂 Windows 「 安裝程式為基礎的安裝程式中使用 MSDE 合併模組。

附註您不能 MSDE 2000 安裝期間設定為 sa 帳戶密碼,藉由使用 Windows 驗證模式。在這種情況下您必須在安裝完成後設定密碼。Microsoft 強烈建議您使用最新的 Service Pack 安裝 MSDE 2000。

Microsoft 建議您使用產生隨機密碼,方法是使用 加密 API 函式,例如:
  • CryptAcquireContext
  • CryptGenRandom
  • CryptCreateHash
  • CryptHashData
如果您使用原生程式碼,使用 CryptReleaseContext

如果您使用 Managed 程式碼,使用 System.Security.Cryptography.RNGCryptoServiceProvider 來取得隨機編碼的字串,然後雜湊值,請使用 System.Security.Cryptography.SHA1 類別 ComputeHash 方法會傳回。隨機字串必須是介於 7 到 20 個字元的可變長度。

如果您忘記 sa 的密碼或您不知道 sa 密碼是什麼,執行個體轉換為混合模式,系統管理員 (sysadmin) 固定的伺服器角色的成員可以重設 sa 密碼不需知道先前的密碼。預設情況下,所有使用者都是本機系統管理員群組的成員都是 系統管理員 (sysadmin) 角色的成員。系統管理員 (sysadmin) 角色的成員可以從 Windows 驗證模式來混合模式或反之亦可變更 MSDE 執行個體,而且可以變更 sa 密碼。因此,基於安全性考量您可能要從 系統管理員 (sysadmin) 角色移除系統管理員群組。

如更多有關如何可以從系統管理員 (sysadmin) 角色移除系統管理員群組的資訊,按一下下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項:
263712如何阻礙 Windows NT 系統管理員從管理叢集的 SQL Server 執行個體


如需有關密碼變更為 [sa 帳戶,請按一下下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項件:
322336如何驗證及變更系統管理員密碼,MSDE 或 SQL Server 2005 Express 版中

附註本文所列的安裝期間變更 sa 密碼的方法只套用到新的 MSDE 的安裝。

下列步驟使用範例原始程式碼來產生隨機的 sa 密碼,然後再啟動 MSDE 安裝。

使用 Microsoft Visual C++.NET

  1. 按一下 [開始],指向 [所有程式]、 都指向 [Microsoft Visual Studio.NET]、 都指向 Visual Studio.NET 工具,然後再按一下 [Visual Studio.NET 命令提示字元]。
  2. 開啟 [記事本]。
  3. 在 [記事本] 中貼上下列程式碼::
    #pragma once
    
    #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers.
    #define UNICODE
    #include <stdio.h>
    #include <windows.h>
    #include <wincrypt.h>
    
    #ifdef UNICODE
    	#define STRNCPY	wcsncpy
    #else
    	#define STRNCPY strncpy
    #endif
    
    #include <atlenc.h>
    
    #define SAPWDSWITCH _T("SAPWD=")
    #define INSTANCENAME _T("INSTANCENAME=MSDETEST")
    
    
    BOOL GenPwd(TCHAR*, int);
    void DisplayError (DWORD);
    
    int main(void)
    {	
    	//Generate random length for password, between 7 and 20 characters.
    	int nPwdLen = ((rand() % 20) + 7) + 1;	//Extra character for null terminator
    	TCHAR* pPwd = new TCHAR[nPwdLen];
    	UINT uRes = 0;
    	DWORD dwRes = 0;
    	if (!GenPwd(pPwd, nPwdLen))
    	{
    		//Failed to generate a password, log the error and return failure.
    		dwRes = GetLastError();
    		DisplayError(dwRes);
    
    		return dwRes;
    	}
    
    
            STARTUPINFO si;
            PROCESS_INFORMATION pi;
    
            ZeroMemory( &si, sizeof(si) );
            si.cb = sizeof(si);
            ZeroMemory( &pi, sizeof(pi) );
    
    	//Allocate a string for the command line.
    	LPTSTR lpCommand = new TCHAR[nPwdLen + _tcslen(INSTANCENAME) + _tcslen(SAPWDSWITCH) + 2];
    
    	_stprintf(lpCommand, _T("%s %s%s"),INSTANCENAME,  SAPWDSWITCH, pPwd);
    // Specify the complete path of Setup.exe.
    	if (!CreateProcess(_T("setup.exe"), lpCommand, NULL, NULL, FALSE, 
    				0, NULL, NULL, &si, &pi))
    	{
    		dwRes = GetLastError();
    		DisplayError(dwRes);
    	}
    	return 0;
    }
    
    
    //Generates a Random string of length nLen - 1.  Buffer ppwd must allocate an extra character for null terminator.
    //Returns TRUE if successful, FALSE if fails.
    //Extended error information can be obtained from GetLastError().
    BOOL GenPwd(TCHAR* ppwd, int nLen)
    {
    	BOOL bResult = FALSE;	//assume failure
    	HCRYPTPROV hProv = NULL;
    	HCRYPTHASH hHash = NULL;
    	
    	//Storage for random string 4 times longer than the resulting password.
    	DWORD dwBufSize = nLen*4;
    	DWORD dwSize = Base64EncodeGetRequiredLength((int)dwBufSize);
    	LPSTR pEncodedString = NULL;
    	LPBYTE pRandomBuf = NULL;
    	TCHAR* pTRandomPwd = NULL;
    	
    	try
    	{
    		pEncodedString = new char[dwSize];
    		pRandomBuf = new BYTE[dwBufSize];
    		
    		// Try to acquire context to Crypto provider.
    		if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT))
    		{
    			if (GetLastError() == NTE_BAD_KEYSET) //Test for non-existent keyset
    			{
    				if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_NEWKEYSET))
    					throw(GetLastError());
    			}
    			else
    				throw(GetLastError());
    		}
    
    		//Generate a random sequence.
    		if (!CryptGenRandom(hProv, dwBufSize, pRandomBuf))
    		{
    			throw(GetLastError());
    		}
    
    		//Get a handle to a hash, then hash the random stream.
    		if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
    		{
    			throw(GetLastError());
    		}
    
    		if (!CryptHashData(hHash, pRandomBuf, dwBufSize, NULL))
    		{
    			throw(GetLastError());
    		}
    	
    		//Destroy the hash object.
    		CryptDestroyHash(hHash);
    		//Release Provider context
    		CryptReleaseContext(hProv, 0);	
    	
    		//Encode the hash value to base64.
    		if (!Base64Encode(pRandomBuf, dwBufSize, pEncodedString, (int*) &dwSize, 0))
    		{
    			throw(GetLastError());
    		}
    	
    		//Determine how many tchars you need to convert string to base64.
    		int nTchars = (int) strlen(pEncodedString);
    	
    		pTRandomPwd = new TCHAR[nTchars];
    	
    #ifdef UNICODE
    		if (MultiByteToWideChar(CP_UTF8, 0, pEncodedString, nTchars, pTRandomPwd, nTchars) == 0)
    		{
    			throw(GetLastError());
    		}
    #else
    		STRNCPY( pTRandomPwd, pEncodedString, nLen);
    #endif
    
    		//Copy the first x characters of random string to output buffer.
    		STRNCPY(ppwd, pTRandomPwd, nLen);
    		//Add null terminator to ppwd string.
    		ppwd[nLen] = _T('\0');
    
    		bResult = TRUE;
    
    	}
    	catch (DWORD)
    	{
    		//Set return value to false.
    		bResult = FALSE;
    	}
    	catch (...)
    	{
    		//Unknown error, throw. 
    		throw;
    	}
    
    	//Clean up memory.
    	if (pRandomBuf)
    	{
    		delete pRandomBuf;
    		pRandomBuf = NULL;
    	}
    
    	if (pEncodedString)
    	{
    		delete pEncodedString;
    		pEncodedString = NULL;
    	}
    
    	if (pTRandomPwd)
    	{
    		delete pTRandomPwd;
    		pTRandomPwd = NULL;
    	}
    
    	return bResult;
    }
    
    
    void DisplayError (DWORD dwError)
    {
    	//Resolve the error code to a message string.
    	LPCTSTR MessageBuffer;
    	DWORD dwBufferLength = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
    		NULL, // module to get message from (NULL == system)
    		dwError,
    		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language.
    		(LPTSTR) &MessageBuffer,
    		0,
    		NULL
    		);
    
    	DWORD dwBytesWritten;
    	// Output message string on stderr.
    	WriteFile(
    		GetStdHandle(STD_ERROR_HANDLE),
    		MessageBuffer,
    		dwBufferLength,
    		&dwBytesWritten,
    		NULL
    		);
    }
    
  4. 將檔案儲存為 StrongSA.cpp
  5. 在命令提示字元下中輸入下列命令編譯程式碼:

    cl strongSA.cpp
  6. 在命令提示字元下中輸入下列命令來執行該程式碼:

    strongSA.exe

使用 Microsoft C#.NET

  1. 在 Visual 的 Studio.NET 中建立一個新 Visual C# 主控台應用程式專案。
  2. 下列程式碼貼在含有 Main 函式的類別檔案。

    請確認程式碼會取代 file:
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Resources;
    using Microsoft.Win32;
    using System.Security.Cryptography;
    
    
    class InstMSDE
    {
    	static void Main(string[] args)
    	{
    		try
    		{   
    			
    
    			// Generate random password.
    			RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    			byte[] encodedSeed = new byte[512];
    			rng.GetBytes(encodedSeed);
    			SHA1 sha1 = SHA1.Create();
    			byte[] hashval = sha1.ComputeHash(encodedSeed);
    			String base64HashVal = Convert.ToBase64String(hashval);
    			// Trim "=" off the end.
    			base64HashVal = base64HashVal.TrimEnd('=');
    				
    			string msdeINI = "setup.ini";
    
    			// You have to set startInfo parameters values as appropriate for your installation.
    			ProcessStartInfo startInfo = new ProcessStartInfo();
    
    			// Setup.exe for MSDE sp3.
    			startInfo.FileName = "setup.exe"; 
    
    			// Pass the SA password to the setup program.
    			startInfo.Arguments = "/settings \"" + msdeINI + "\"" + " SAPWD=" + base64HashVal + " /qr+ "; 
    			startInfo.WindowStyle = ProcessWindowStyle.Normal;
    			// Substitute the workdir with complete path of installation folder. 
    			startInfo.WorkingDirectory = "c:\\Workingdir";
    				
    			Process.Start(startInfo);
    			
    			
    		}
    		catch (Exception e)
    		{
    			Console.WriteLine("Unable to execute program due to the following error: " + e.Message);
    			return;
    		}  
    	}
    }
    
  3. 按下 F5 以編譯,並執行程式。

?考

如需有關如何在自訂應用程式安裝程式中內嵌 MSDE 的詳細資訊,請造訪下列 Microsoft 網站]:
Embedding MSDE 2000 Setup in the Setup of Custom Applications

屬性

文章編號: 814463 - 上次校閱: 2007年3月22日 - 版次: 1.5
這篇文章中的資訊適用於:
  • Microsoft SQL Server 2000 Desktop Engine (Windows)
關鍵字:?
kbmt kbsetup kbsecurity kblogin kbauthentication kbsample kbguidelines kbcode kbinfo KB814463 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:814463
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。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