Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
В этой статье описывается, как передавать имена входа и пароли между различными экземплярами Microsoft SQL Server, работающими в Windows. Экземпляры могут находиться на одном сервере или на разных серверах, а их версии могут отличаться.
Исходная версия продукта: SQL Server
Исходный номер базы знаний: 918992, 246133
Зачем передавать имена входа между экземплярами SQL Server?
В этой статье сервер A и сервер B являются серверами.
После перемещения базы данных из экземпляра SQL Server на сервер A на экземпляр SQL Server на сервер B пользователи могут не входить на сервер базы данных на сервере B. Кроме того, пользователи могут получить следующее сообщение об ошибке:
Сбой входа для пользователя "MyUser". (Microsoft SQL Server, ошибка: 18456)
Эта проблема возникает из-за того, что имена входа из экземпляра SQL Server на сервере A не существуют в экземпляре SQL Server на сервере B.
Помните, что ошибка 18456 возникает по многим другим причинам. Дополнительные сведения об этих причинах и их решениях см . в MSSQLSERVER_18456.
Шаги по передаче имен входа между экземплярами SQL Server
Чтобы передать имена входа, воспользуйтесь одним из описанных ниже способов в зависимости от ситуации.
Метод 1. Создание скриптов с помощью SSMS на исходном сервере и сброс паролей для входа SQL Server на целевом сервере вручную
Скрипты входа можно создать в SQL Server Management Studio (SSMS) с помощью параметра "Создать скрипты" для базы данных.
Чтобы создать скрипты с помощью SSMS на исходном сервере и вручную сбросить пароли для входа SQL Server на целевом сервере, выполните следующие действия.
Подключитесь к серверу A, на котором размещен исходный SQL Server.
Разверните узел Базы данных .
Щелкните правой кнопкой мыши любую пользовательную базу данных и выберите "Задачи>создания скриптов".
Откроется страница Введение. Нажмите кнопку "Рядом", чтобы открыть страницу "Выбор объектов". Выберите Внести в скрипт всю базу данных целиком вместе со всеми объектами.
Нажмите кнопку Далее, чтобы открыть страницу Задание параметров скриптов.
Нажмите кнопку "Дополнительно" для параметров входа в скрипт.
В списке "Дополнительно" найдите имена входа скриптов, установите значение True и нажмите кнопку "ОК".
Вернитесь в раздел " Настройка параметров скриптов" в разделе "Выбор способа сохранения скриптов" и нажмите кнопку "Открыть" в новом окне запроса.
Дважды нажмите кнопку "Далее ", а затем нажмите кнопку "Готово".
Найдите раздел в скрипте, который содержит имена входа. Как правило, созданный скрипт содержит текст со следующим комментарием в начале этого раздела:
/* For security reasons the login is created disabled and with a random password. */Примечание.
Это означает, что имена входа проверки подлинности SQL Server создаются случайным паролем и отключены по умолчанию. Необходимо сбросить пароль и повторно включить эти имена входа на целевом сервере.
Примените скрипт входа из более крупного созданного скрипта к целевому SQL Server.
Для всех имен входа проверки подлинности SQL Server сбросьте пароль в целевом SQL Server и повторно включите эти имена входа.
Метод 2. Передача имен входа и паролей на конечный сервер (Сервер B) с помощью скриптов, созданных на исходном сервере (Сервер A)
Создайте хранимые процедуры, которые помогут создать необходимые сценарии для передачи имен входа и паролей. Для этого подключитесь к серверу A с помощью SQL Server Management Studio (SSMS) или любого другого клиентского средства и запустите следующий сценарий:
USE [master] GO IF OBJECT_ID('dbo.sp_hexadecimal') IS NOT NULL DROP PROCEDURE dbo.sp_hexadecimal GO CREATE PROCEDURE dbo.sp_hexadecimal @binvalue [varbinary](256) ,@hexvalue [nvarchar] (514) OUTPUT AS BEGIN DECLARE @i [smallint] DECLARE @length [smallint] DECLARE @hexstring [nchar](16) SELECT @hexvalue = N'0x' SELECT @i = 1 SELECT @length = DATALENGTH(@binvalue) SELECT @hexstring = N'0123456789ABCDEF' WHILE (@i < = @length) BEGIN DECLARE @tempint [smallint] DECLARE @firstint [smallint] DECLARE @secondint [smallint] SELECT @tempint = CONVERT([smallint], SUBSTRING(@binvalue, @i, 1)) SELECT @firstint = FLOOR(@tempint / 16) SELECT @secondint = @tempint - (@firstint * 16) SELECT @hexvalue = @hexvalue + SUBSTRING(@hexstring, @firstint + 1, 1) + SUBSTRING(@hexstring, @secondint + 1, 1) SELECT @i = @i + 1 END END GO IF OBJECT_ID('dbo.sp_help_revlogin') IS NOT NULL DROP PROCEDURE dbo.sp_help_revlogin GO CREATE PROCEDURE dbo.sp_help_revlogin @login_name [sysname] = NULL AS BEGIN DECLARE @name [sysname] DECLARE @type [nvarchar](1) DECLARE @hasaccess [int] DECLARE @denylogin [int] DECLARE @is_disabled [int] DECLARE @PWD_varbinary [varbinary](256) DECLARE @PWD_string [nvarchar](514) DECLARE @SID_varbinary [varbinary](85) DECLARE @SID_string [nvarchar](514) DECLARE @tmpstr [nvarchar](4000) DECLARE @is_policy_checked [nvarchar](3) DECLARE @is_expiration_checked [nvarchar](3) DECLARE @Prefix [nvarchar](4000) DECLARE @defaultdb [sysname] DECLARE @defaultlanguage [sysname] DECLARE @tmpstrRole [nvarchar](4000) 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,default_language_name = ISNULL(p.default_language_name,@@LANGUAGE) FROM sys.server_principals p LEFT JOIN sys.syslogins l ON l.[name] = p.[name] WHERE p.[type] IN ('S' /* SQL_LOGIN */,'G' /* WINDOWS_GROUP */,'U' /* WINDOWS_LOGIN */) 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,default_language_name = ISNULL(p.default_language_name,@@LANGUAGE) FROM sys.server_principals p LEFT JOIN sys.syslogins l ON l.[name] = p.[name] WHERE p.[type] IN ('S' /* SQL_LOGIN */,'G' /* WINDOWS_GROUP */,'U' /* WINDOWS_LOGIN */) AND p.[name] <> 'sa' AND p.[name] NOT LIKE '##%' 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 for ' + QUOTENAME(@login_name) + N'. */' CLOSE login_curs DEALLOCATE login_curs RETURN - 1 END SET @tmpstr = N'/* sp_help_revlogin script ** Generated ' + CONVERT([nvarchar], GETDATE()) + N' on ' + @@SERVERNAME + N' */' PRINT @tmpstr WHILE (@@fetch_status <> - 1) BEGIN IF (@@fetch_status <> - 2) BEGIN PRINT '' SET @tmpstr = N'/* Login ' + QUOTENAME(@name) + N' */' PRINT @tmpstr SET @tmpstr = N'IF NOT EXISTS ( SELECT 1 FROM sys.server_principals WHERE [name] = N''' + @name + N''' ) BEGIN' PRINT @tmpstr IF @type IN ('G','U') -- NT-authenticated Group/User BEGIN -- NT authenticated account/group SET @tmpstr = N' CREATE LOGIN ' + QUOTENAME(@name) + N' FROM WINDOWS WITH DEFAULT_DATABASE = ' + QUOTENAME(@defaultdb) + N' ,DEFAULT_LANGUAGE = ' + QUOTENAME(@defaultlanguage) END ELSE BEGIN -- SQL Server authentication -- obtain password and sid SET @PWD_varbinary = CAST(LOGINPROPERTY(@name, 'PasswordHash') AS [varbinary](256)) EXEC dbo.sp_hexadecimal @PWD_varbinary, @PWD_string OUT EXEC dbo.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 = NCHAR(9) + N'CREATE LOGIN ' + QUOTENAME(@name) + N' WITH PASSWORD = ' + @PWD_string + N' HASHED ,SID = ' + @SID_string + N' ,DEFAULT_DATABASE = ' + QUOTENAME(@defaultdb) + N' ,DEFAULT_LANGUAGE = ' + QUOTENAME(@defaultlanguage) IF @is_policy_checked IS NOT NULL BEGIN SET @tmpstr = @tmpstr + N' ,CHECK_POLICY = ' + @is_policy_checked END IF @is_expiration_checked IS NOT NULL BEGIN SET @tmpstr = @tmpstr + N' ,CHECK_EXPIRATION = ' + @is_expiration_checked END END IF (@denylogin = 1) BEGIN -- login is denied access SET @tmpstr = @tmpstr + NCHAR(13) + NCHAR(10) + NCHAR(9) + N'' + NCHAR(13) + NCHAR(10) + NCHAR(9) + N'DENY CONNECT SQL TO ' + QUOTENAME(@name) END ELSE IF (@hasaccess = 0) BEGIN -- login exists but does not have access SET @tmpstr = @tmpstr + NCHAR(13) + NCHAR(10) + NCHAR(9) + N'' + NCHAR(13) + NCHAR(10) + NCHAR(9) + N'REVOKE CONNECT SQL TO ' + QUOTENAME(@name) END IF (@is_disabled = 1) BEGIN -- login is disabled SET @tmpstr = @tmpstr + NCHAR(13) + NCHAR(10) + NCHAR(9) + N'' + NCHAR(13) + NCHAR(10) + NCHAR(9) + N'ALTER LOGIN ' + QUOTENAME(@name) + N' DISABLE' END SET @Prefix = NCHAR(13) + NCHAR(10) + NCHAR(9) + N'' + NCHAR(13) + NCHAR(10) + NCHAR(9) + N'EXEC [master].dbo.sp_addsrvrolemember @loginame = N''' SET @tmpstrRole = N'' SELECT @tmpstrRole = @tmpstrRole + CASE WHEN sysadmin = 1 THEN @Prefix + LoginName + N''', @rolename = N''sysadmin''' ELSE '' END + CASE WHEN securityadmin = 1 THEN @Prefix + LoginName + N''', @rolename = N''securityadmin''' ELSE '' END + CASE WHEN serveradmin = 1 THEN @Prefix + LoginName + N''', @rolename = N''serveradmin''' ELSE '' END + CASE WHEN setupadmin = 1 THEN @Prefix + LoginName + N''', @rolename = N''setupadmin''' ELSE '' END + CASE WHEN processadmin = 1 THEN @Prefix + LoginName + N''', @rolename = N''processadmin''' ELSE '' END + CASE WHEN diskadmin = 1 THEN @Prefix + LoginName + N''', @rolename = N''diskadmin''' ELSE '' END + CASE WHEN dbcreator = 1 THEN @Prefix + LoginName + N''', @rolename = N''dbcreator''' ELSE '' END + CASE WHEN bulkadmin = 1 THEN @Prefix + LoginName + N''', @rolename = N''bulkadmin''' ELSE '' END FROM ( SELECT 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 IF @tmpstr <> '' PRINT @tmpstr IF @tmpstrRole <> '' 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Примечание.
Этот сценарий создает две хранимые процедуры в главной базе данных. Эти процедуры называются sp_hexadecimal и sp_help_revlogin.
В редакторе запросов SSMS выберите параметр Результаты в текст.
Выполните следующую инструкцию в том же или новом окне запроса:
EXEC sp_help_revloginСценарий вывода, который создает хранимая процедура
sp_help_revlogin, является сценарием входа. Этот сценарий входа создает имена входа с исходным идентификатором безопасности (SID) и исходным паролем.Просмотрите и следуйте инструкциям в разделе "Дополнительные рекомендации по передаче имен входа SQL Server ", прежде чем продолжить реализацию шагов на целевом сервере.
После реализации любых применимых шагов из дополнительных рекомендаций при передаче имен входа SQL Server подключитесь к целевому серверу B с помощью любого клиентского средства (например, SSMS).
Запустите скрипт, созданный в качестве выходных
sp_helprevloginданных сервера A.
Дополнительные рекомендации при передаче имен входа SQL Server
Перед запуском сценария вывода на экземпляре на сервере B просмотрите следующие сведения:
Понимание хэширования паролей при передаче данных входа в SQL Server
Хэширование пароля может выполняться следующими способами:
-
VERSION_SHA1: этот хэш создается с помощью алгоритма SHA1 и используется в SQL Server, начиная с версии от 2000 до 2008 R2. -
VERSION_SHA2: этот хэш создается с помощью алгоритма SHA2 512 и используется в SQL Server 2012 и более поздних версиях.
-
В сценарии вывода имена входа создаются с помощью зашифрованного пароля. Это связано с аргументом
HASHEDв инструкцииCREATE LOGIN. Этот аргумент указывает, что пароль, введенный послеPASSWORDхэшированного аргумента.
Обработка изменений домена во время передачи имени входа SQL Server
Являются ли исходные и целевые серверы в разных доменах? Внимательно просмотрите сценарий вывода. Если сервер A и сервер B находятся в разных доменах, необходимо изменить сценарий вывода. Затем необходимо заменить исходное доменное имя с помощью нового доменного имени в CREATE LOGIN инструкциях. Интегрированные имена входа, которым предоставлен доступ в новом домене, не имеют того же идентификатора безопасности, что и имена входа в исходном домене. Таким образом, пользователи будут потеряны из-за этих имен входа. Дополнительные сведения о том, как устранить этих потерянных пользователей, см. в разделе "Устранение неполадок потерянных пользователей" (SQL Server) и ALTER USER.
Если сервер A и сервер B находятся в одном домене, используется один и тот же идентификатор безопасности. Поэтому пользователи вряд ли будут потеряны.
Необходимые разрешения для просмотра и выбора учетных записей SQL Server
По умолчанию только член предопределенной роли сервера sysadmin может выполнять инструкцию SELECT из представления sys.server_principals. Если член предопределенной роли сервера sysadmin не предоставляет пользователям необходимые разрешения, пользователи не могут создать или запустить выходной скрипт.
Параметр базы данных по умолчанию не выполняется скриптом и не передается
Действия, описанные в этой статье, не передают сведения о базе данных по умолчанию для определенного имени входа. Это связано с тем, что база данных по умолчанию может не всегда существовать на сервере B. Чтобы определить базу данных по умолчанию для входа, используйте ALTER LOGIN инструкцию, передав имя входа и базу данных по умолчанию в качестве аргументов.
Управление различиями порядка сортировки при передаче логинов в SQL Server
Могут быть различия в заказах сортировки между исходными и целевыми серверами, или они могут быть одинаковыми. Вот как можно решить каждый сценарий:
Нечувствительный к регистру сервер A и сервер с учетом регистра B: порядок сортировки сервера A может быть не учитывает регистр, а порядок сортировки сервера B может быть учитывает регистр. В этом случае пользователи должны ввести пароли заглавными буквами после передачи имен входа и паролей экземпляру на сервере B.
Сервер С учетом регистра А и нечувствительный к регистру сервер B: порядок сортировки сервера A может быть учитывает регистр, а порядок сортировки сервера B может быть не учитывает регистр. В этом случае пользователи не могут войти с помощью имен входа и паролей, передаваемых экземпляру на сервере B, если только одно из следующих условий не имеет значения true:
- Исходные пароли не содержат букв.
- Исходные пароли содержат только прописные буквы.
Учитывает регистр или не учитывает регистр на обоих серверах: порядок сортировки сервера А и сервера B может быть учитывает регистр, или порядок сортировки сервера A и сервера B может быть нечувствительным к регистру. В таких случаях пользователи не сталкиваются с проблемой.
Устранение конфликтов с существующими именами входа SQL Server на целевом сервере
Скрипт предназначен для проверки наличия имени входа на целевом сервере и создания имени входа только в том случае, если это не так. Однако если при запуске скрипта вывода на сервере B вы получите следующее сообщение об ошибке, необходимо вручную устранить его, выполнив действия, описанные в этом разделе.
Сообщение 15025, уровень 16, состояние 1, строка 1
Субъект-сервер "MyLogin" уже существует.
Аналогичным образом, имя входа, которое уже находится в экземпляре на сервере B, может иметь идентификатор безопасности, который совпадает с идентификатором безопасности в выходном скрипте. В этом случае при запуске сценария вывода на экземпляре на сервере B отобразится следующее сообщение об ошибке:
Сообщение 15433, уровень 16, состояние 1, строка 1, «Предоставленный параметр для идентификатора безопасности уже используется».
Чтобы устранить проблему вручную, выполните следующие действия.
- Внимательно просмотрите сценарий вывода.
- Проверьте содержимое
sys.server_principalsпредставления в экземпляре на сервере B. - Устраните эти сообщения об ошибках соответствующим образом.
Начиная с SQL Server 2005, идентификатор безопасности для входа используется для управления доступом на уровне базы данных. Иногда при сопоставлении с пользователями в разных базах данных имена входа могут иметь разные идентификаторы безопасности. Эта проблема может возникнуть, если базы данных объединяются вручную с разных серверов. В таких случаях имя входа может получить доступ только к базе данных, где идентификатор безопасности субъекта базы данных соответствует идентификатору безопасности в представлении sys.server_principals . Чтобы устранить эту проблему, вручную удалите пользователя базы данных с несогласованным идентификатором безопасности с помощью инструкции DROP USER . Затем снова добавьте пользователя с инструкцией CREATE USER и сопоставите его с правильным именем входа (субъект сервера).
Дополнительные сведения и различия серверов от субъектов базы данных см. в статье CREATE USER и CREATE LOGIN.