Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Исходная версия продукта: SQL Server
Исходный номер базы знаний: 918992, 246133
Сводка
В этой статье описывается, как передавать имена входа и пароли между различными экземплярами Microsoft SQL Server , работающими в Windows. Используйте эти процедуры при переносе баз данных между серверами или необходимости поддерживать согласованный доступ пользователей между экземплярами SQL Server. Экземпляры могут находиться на одном сервере или на разных серверах, а их версии могут отличаться.
Зачем передавать имена входа между экземплярами SQL Server?
При перемещении базы данных на новый сервер (например, во время миграции или восстановления) перемещаются пользователи базы данных, но их соответствующие серверные логины могут отсутствовать в новом экземпляре. Это условие создает потерянных пользователей. Передача имен входа и паролей имеет решающее значение для обеспечения безопасности и непрерывности доступа.
После перемещения базы данных из экземпляра SQL Server на сервер A на экземпляр SQL Server на сервер B пользователи могут не входить на сервер базы данных на сервере B. Кроме того, пользователи могут получить следующее сообщение об ошибке:
Сбой входа для пользователя "MyUser". (Microsoft SQL Server, ошибка: 18456)
Эта проблема возникает из-за того, что имена входа из экземпляра SQL Server на сервере A не существуют в экземпляре SQL Server на сервере B.
Ошибка 18456 также может возникать по нескольким другим причинам. Дополнительные сведения о различных причинах и их решениях см. в MSSQLSERVER_18456.
Шаги по передаче имен входа между экземплярами SQL Server
Чтобы передать имена входа, используйте один из следующих методов, как это подходит для вашей ситуации.
Создавайте сценарии с помощью 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 и повторно включите эти имена входа.
Передача имен входа и паролей на целевой сервер (Сервер 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: SQL Server использует алгоритм SHA1 для создания этого хэша. Версии SQL Server 2000 до SQL Server 2008 R2 используют этот хэш. -
VERSION_SHA2: SQL Server использует алгоритм SHA2 512 для создания этого хэша. Версии SQL Server 2012 и более поздних версий используют этот хэш.
Выходной скрипт создает имена входа с помощью зашифрованного пароля. Аргумент HASHED в инструкции CREATE LOGIN вызывает это поведение. Этот аргумент указывает, что пароль, введенный после аргумента PASSWORD, уже хэширован.
Обработка изменений домена во время передачи имени входа SQL Server
Если исходные и конечные серверы находятся в разных доменах, внимательно просмотрите выходной скрипт. Необходимо изменить выходной скрипт и заменить исходное доменное имя новым доменным именем в 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.
Сервер A, чувствительный к регистру, и сервер B, нечувствительный к регистру: Порядок сортировки сервера A учитывает регистр, а порядок сортировки сервера B не учитывает регистр. В этом случае пользователи не могут войти с помощью имен входа и паролей, передаваемых на экземпляр на сервере 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.