Transferowanie identyfikatorów logowania i haseł między wystąpieniami SQL Server
W tym artykule opisano sposób przenoszenia identyfikatorów logowania i haseł między różnymi wystąpieniami SQL Server uruchomionych w systemie Windows.
Oryginalna wersja produktu: SQL Server
Oryginalny numer KB: 918992, 246133
Wprowadzenie
W tym artykule opisano sposób przenoszenia identyfikatorów logowania i haseł między różnymi wystąpieniami usługi Microsoft SQL Server.
Uwaga
Wystąpienia mogą znajdować się na tym samym serwerze lub na różnych serwerach, a ich wersje mogą się różnić.
Więcej informacji
W tym artykule serwery A i serwer B są różnymi serwerami.
Po przeniesieniu bazy danych z wystąpienia SQL Server na serwerze A do wystąpienia SQL Server na serwerze B użytkownicy mogą nie być w stanie zalogować się do bazy danych na serwerze B. Ponadto użytkownicy mogą otrzymać następujący komunikat o błędzie:
Logowanie użytkownika 'MyUser' nie powiodło się. (System Microsoft SQL Server Compact, błąd: 18456)
Ten problem występuje, ponieważ nie przetransferowaliśmy identyfikatorów logowania i haseł z wystąpienia SQL Server na serwerze A do wystąpienia SQL Server na serwerze B.
Uwaga
Komunikat o błędzie 18456 występuje również z innych powodów. Aby uzyskać dodatkowe informacje na temat tych przyczyn i potencjalnych rozwiązań, zobacz MSSQLSERVER_18456.
W celu przeniesienia loginów zastosuj jedną z następujących metod zależnie od systemu operacyjnego:
Metoda 1. Resetowanie hasła na komputerze docelowym SQL Server (serwer B).
Aby rozwiązać ten problem, zresetuj hasło na SQL Server komputerze, a następnie wyprowadź skrypt logowania.
Uwaga
Podczas resetowania hasła używany jest algorytm wyznaczania skrótu hasła.
Metoda 2. Transferowanie identyfikatorów logowania i haseł na serwer docelowy (serwer B) przy użyciu skryptów generowanych na serwerze źródłowym (serwer A).
Utwórz procedury składowane, które pomogą wygenerować skrypty niezbędne do transferu identyfikatorów logowania i ich haseł. W tym celu połącz się z serwerem A przy użyciu SQL Server Management Studio (SSMS) lub dowolnego innego narzędzia klienckiego i uruchom następujący skrypt:
USE [master] GO IF OBJECT_ID ('sp_hexadecimal') IS NOT NULL DROP PROCEDURE sp_hexadecimal GO CREATE PROCEDURE [dbo].[sp_hexadecimal] ( @binvalue varbinary(256), @hexvalue varchar (514) OUTPUT ) AS BEGIN DECLARE @charvalue varchar (514) DECLARE @i int DECLARE @length int DECLARE @hexstring char(16) SELECT @charvalue = '0x' SELECT @i = 1 SELECT @length = DATALENGTH (@binvalue) SELECT @hexstring = '0123456789ABCDEF' WHILE (@i <= @length) BEGIN DECLARE @tempint int DECLARE @firstint int DECLARE @secondint int SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1)) SELECT @firstint = FLOOR(@tempint/16) SELECT @secondint = @tempint - (@firstint*16) SELECT @charvalue = @charvalue + SUBSTRING(@hexstring, @firstint+1, 1) + SUBSTRING(@hexstring, @secondint+1, 1) SELECT @i = @i + 1 END SELECT @hexvalue = @charvalue END go IF OBJECT_ID ('sp_help_revlogin') IS NOT NULL DROP PROCEDURE sp_help_revlogin GO CREATE PROCEDURE [dbo].[sp_help_revlogin] ( @login_name sysname = NULL ) AS BEGIN DECLARE @name SYSNAME DECLARE @type VARCHAR (1) DECLARE @hasaccess INT DECLARE @denylogin INT DECLARE @is_disabled INT DECLARE @PWD_varbinary VARBINARY (256) DECLARE @PWD_string VARCHAR (514) DECLARE @SID_varbinary VARBINARY (85) DECLARE @SID_string VARCHAR (514) DECLARE @tmpstr VARCHAR (1024) DECLARE @is_policy_checked VARCHAR (3) DECLARE @is_expiration_checked VARCHAR (3) Declare @Prefix VARCHAR(255) DECLARE @defaultdb SYSNAME DECLARE @defaultlanguage SYSNAME DECLARE @tmpstrRole VARCHAR (1024) IF (@login_name IS NULL) BEGIN DECLARE login_curs CURSOR FOR SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin, p.default_language_name FROM sys.server_principals p LEFT JOIN sys.syslogins l ON ( l.name = p.name ) WHERE p.type IN ( 'S', 'G', 'U' ) AND p.name <> 'sa' AND p.name not like '##%' ORDER BY p.name END ELSE DECLARE login_curs CURSOR FOR SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin, p.default_language_name FROM sys.server_principals p LEFT JOIN sys.syslogins l ON ( l.name = p.name ) WHERE p.type IN ( 'S', 'G', 'U' ) AND p.name = @login_name ORDER BY p.name OPEN login_curs FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin, @defaultlanguage IF (@@fetch_status = -1) BEGIN PRINT 'No login(s) found.' CLOSE login_curs DEALLOCATE login_curs RETURN -1 END SET @tmpstr = '/* sp_help_revlogin script ' PRINT @tmpstr SET @tmpstr = '** Generated ' + CONVERT (varchar, GETDATE()) + ' on ' + @@SERVERNAME + ' */' PRINT @tmpstr PRINT '' WHILE (@@fetch_status <> -1) BEGIN IF (@@fetch_status <> -2) BEGIN PRINT '' SET @tmpstr = '-- Login: ' + @name PRINT @tmpstr SET @tmpstr='IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'''+@name+''') BEGIN' Print @tmpstr IF (@type IN ( 'G', 'U')) BEGIN -- NT authenticated account/group SET @tmpstr = 'CREATE LOGIN ' + QUOTENAME( @name ) + ' FROM WINDOWS WITH DEFAULT_DATABASE = [' + @defaultdb + ']' + ', DEFAULT_LANGUAGE = [' + @defaultlanguage + ']' END ELSE BEGIN -- SQL Server authentication -- obtain password and sid SET @PWD_varbinary = CAST( LOGINPROPERTY( @name, 'PasswordHash' ) AS varbinary (256) ) EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT EXEC sp_hexadecimal @SID_varbinary,@SID_string OUT -- obtain password policy state SELECT @is_policy_checked = CASE is_policy_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name SELECT @is_expiration_checked = CASE is_expiration_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name SET @tmpstr = 'CREATE LOGIN ' + QUOTENAME( @name ) + ' WITH PASSWORD = ' + @PWD_string + ' HASHED, SID = ' + @SID_string + ', DEFAULT_DATABASE = [' + @defaultdb + ']' + ', DEFAULT_LANGUAGE = [' + @defaultlanguage + ']' IF ( @is_policy_checked IS NOT NULL ) BEGIN SET @tmpstr = @tmpstr + ', CHECK_POLICY = ' + @is_policy_checked END IF ( @is_expiration_checked IS NOT NULL ) BEGIN SET @tmpstr = @tmpstr + ', CHECK_EXPIRATION = ' + @is_expiration_checked END END IF (@denylogin = 1) BEGIN -- login is denied access SET @tmpstr = @tmpstr + '; DENY CONNECT SQL TO ' + QUOTENAME( @name ) END ELSE IF (@hasaccess = 0) BEGIN -- login exists but does not have access SET @tmpstr = @tmpstr + '; REVOKE CONNECT SQL TO ' + QUOTENAME( @name ) END IF (@is_disabled = 1) BEGIN -- login is disabled SET @tmpstr = @tmpstr + '; ALTER LOGIN ' + QUOTENAME( @name ) + ' DISABLE' END SET @Prefix = ' EXEC master.dbo.sp_addsrvrolemember @loginame=''' SET @tmpstrRole='' SELECT @tmpstrRole = @tmpstrRole + CASE WHEN sysadmin = 1 THEN @Prefix + [LoginName] + ''', @rolename=''sysadmin''' ELSE '' END + CASE WHEN securityadmin = 1 THEN @Prefix + [LoginName] + ''', @rolename=''securityadmin''' ELSE '' END + CASE WHEN serveradmin = 1 THEN @Prefix + [LoginName] + ''', @rolename=''serveradmin''' ELSE '' END + CASE WHEN setupadmin = 1 THEN @Prefix + [LoginName] + ''', @rolename=''setupadmin''' ELSE '' END + CASE WHEN processadmin = 1 THEN @Prefix + [LoginName] + ''', @rolename=''processadmin''' ELSE '' END + CASE WHEN diskadmin = 1 THEN @Prefix + [LoginName] + ''', @rolename=''diskadmin''' ELSE '' END + CASE WHEN dbcreator = 1 THEN @Prefix + [LoginName] + ''', @rolename=''dbcreator''' ELSE '' END + CASE WHEN bulkadmin = 1 THEN @Prefix + [LoginName] + ''', @rolename=''bulkadmin''' ELSE '' END FROM ( SELECT CONVERT(VARCHAR(100),SUSER_SNAME(sid)) AS [LoginName], sysadmin, securityadmin, serveradmin, setupadmin, processadmin, diskadmin, dbcreator, bulkadmin FROM sys.syslogins WHERE ( sysadmin<>0 OR securityadmin<>0 OR serveradmin<>0 OR setupadmin <>0 OR processadmin <>0 OR diskadmin<>0 OR dbcreator<>0 OR bulkadmin<>0 ) AND name=@name ) L PRINT @tmpstr PRINT @tmpstrRole PRINT 'END' END FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin, @defaultlanguage END CLOSE login_curs DEALLOCATE login_curs RETURN 0 END
Uwaga
Ten skrypt tworzy dwie procedury składowane w głównej bazie danych. Procedury są nazywane sp_hexadecimal i sp_help_revlogin.
W edytorze zapytań SSMS wybierz opcję Wyniki do tekstu.
Uruchom następującą instrukcję w tym samym lub nowym oknie zapytania:
EXEC sp_help_revlogin
Skrypt wyjściowy generowany przez procedurę składowaną
sp_help_revlogin
to skrypt logowania. Ten skrypt logowania tworzy identyfikatory logowania z oryginalnym identyfikatorem zabezpieczeń (SID) i oryginalnym hasłem.
Ważna
Zapoznaj się z informacjami w poniższej sekcji Uwagi przed kontynuowaniem implementowania kroków na serwerze docelowym.
Kroki na serwerze docelowym (serwer B)
Połącz się z serwerem B przy użyciu dowolnego narzędzia klienckiego (takiego jak SSMS), a następnie uruchom skrypt wygenerowany w kroku 4 (dane wyjściowe sp_helprevlogin
) z serwera A.
Uwagi
Przed uruchomieniem skryptu wyjściowego na wystąpieniu na serwerze B przejrzyj następujące informacje:
Hasło może być skrótem w następujący sposób:
VERSION_SHA1
: Ten skrót jest generowany przy użyciu algorytmu SHA1 i jest używany w SQL Server od 2000 do SQL Server 2008 R2.VERSION_SHA2
: Ten skrót jest generowany przy użyciu algorytmu SHA2 512 i jest używany w wersjach SQL Server 2012 i nowszych.
Dokładnie przejrzyj skrypt wyjściowy. Jeśli serwer A i serwer B znajdują się w różnych domenach, musisz zmienić skrypt wyjściowy. Następnie należy zastąpić oryginalną nazwę domeny przy użyciu nowej nazwy domeny w
CREATE LOGIN
instrukcjach. Zintegrowane identyfikatory logowania, którym udzielono dostępu w nowej domenie, nie mają takiego samego identyfikatora SID jak identyfikatory logowania w oryginalnej domenie. W związku z tym użytkownicy są oddzieleni od tych identyfikatorów logowania. Aby uzyskać więcej informacji na temat sposobu rozwiązywania problemów z tymi oddzielonym użytkownikami, zobacz Rozwiązywanie problemów z oddzielonym użytkownikiem (SQL Server) i ALTER USER.
Jeśli serwer A i serwer B znajdują się w tej samej domenie, jest używany ten sam identyfikator SID. Dlatego jest mało prawdopodobne, że użytkownicy zostaną oddzieleni.W skrypcie danych wyjściowych nazwy logowania są tworzone przy użyciu zaszyfrowanego hasła. Wynika to z argumentu HASHED w instrukcji
CREATE LOGIN
. Ten argument określa, że hasło wprowadzone po utworzeniu argumentu PASSWORD jest już skrótem.Domyślnie tylko członek stałej roli serwera sysadmin może uruchamiać instrukcję
SELECT
z widokusys.server_principals
. Jeśli członek stałej roli serwera sysadmin nie przyzna użytkownikom niezbędnych uprawnień, użytkownicy nie mogą tworzyć ani uruchamiać skryptu wyjściowego.Kroki opisane w tym artykule nie przesyłają domyślnych informacji o bazie danych dla określonego identyfikatora logowania. Dzieje się tak, ponieważ domyślna baza danych może nie zawsze istnieć na serwerze B. Aby zdefiniować domyślną bazę danych logowania, użyj
ALTER LOGIN
instrukcji , przekazując nazwę logowania i domyślną bazę danych jako argumenty.Sortuj zamówienia na serwerach źródłowych i docelowych:
Bez uwzględniania wielkości liter serwer A i serwer z rozróżnianiem wielkości liter B: kolejność sortowania serwera A może być uwzględniana wielkością liter, a kolejność sortowania serwera B może uwzględniać wielkość liter. W takim przypadku użytkownicy muszą wpisać hasła we wszystkich wielkich literach po przeniesieniu identyfikatorów logowania i haseł do wystąpienia na serwerze B.
Serwer Z rozróżnianiem wielkości liter A i bez uwzględniania wielkości liter B: Kolejność sortowania serwera A może uwzględniać wielkość liter, a kolejność sortowania serwera B może być bez uwzględniania wielkości liter. W takim przypadku użytkownicy nie mogą się zalogować przy użyciu identyfikatorów logowania i haseł przesyłanych do wystąpienia na serwerze B, chyba że spełniony jest jeden z następujących warunków:
- Oryginalne hasła nie zawierają żadnych liter.
- Wszystkie litery w oryginalnych hasłach są wielkimi literami.
Uwzględniana wielkość liter lub wielkość liter na obu serwerach: kolejność sortowania serwera A i serwera B może uwzględniać wielkość liter lub kolejność sortowania serwera A i serwera B może być uwzględniana wielkością liter. W takich przypadkach użytkownicy nie doświadczają problemu.
Identyfikator logowania, który jest już w wystąpieniu na serwerze B, może mieć taką samą nazwę jak nazwa w skryptze danych wyjściowych. W takim przypadku podczas uruchamiania skryptu wyjściowego na wystąpieniu na serwerze B zostanie wyświetlony następujący komunikat o błędzie:
Komunikat 15025, Poziom 16, Stan 1, Wiersz 1
Jednostka serwera 'MyLogin' już istnieje.Podobnie logowanie, które już znajduje się w wystąpieniu na serwerze B, może mieć identyfikator SID, który jest taki sam jak identyfikator SID w skryptze danych wyjściowych. W takim przypadku podczas uruchamiania skryptu wyjściowego na wystąpieniu na serwerze B zostanie wyświetlony następujący komunikat o błędzie:
Komunikat 15433, Poziom 16, Stan 1, Wiersz 1 Podany identyfikator sid parametru jest w użyciu.
Z tego powodu należy wykonać następujące czynności:
Dokładnie przejrzyj skrypt wyjściowy.
Sprawdź zawartość
sys.server_principals
widoku w wystąpieniu na serwerze B.W razie potrzeby rozwiąż te komunikaty o błędach.
W systemie SQL Server 2005 identyfikator SID logowania jest używany do implementowania dostępu na poziomie bazy danych. Identyfikatory logowania mogą mieć różne identyfikatory SID w różnych bazach danych na serwerze. W takim przypadku logowanie może uzyskać dostęp tylko do bazy danych, która ma identyfikator SID zgodny z identyfikatorem SID w widoku
sys.server_principals
. Ten problem może wystąpić, jeśli dwie bazy danych są łączone z różnych serwerów. Aby rozwiązać ten problem, ręcznie usuń identyfikator logowania z bazy danych z niezgodnością identyfikatora SID przy użyciu instrukcji DROP USER. Następnie dodaj ponownie identyfikator logowania przy użyciu instrukcjiCREATE USER
.
Informacje
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla