Передача логинов и паролей между экземплярами SQL Server

1484
Передача логинов и паролей между экземплярами SQL Server
Передача логинов и паролей между экземплярами 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.

Чтобы передать логины, используйте один из следующих методов, соответствующих вашей ситуации.

  • Метод 1. Сброс пароля на компьютере назначения SQL Server (Сервер B)Чтобы устранить эту проблему, сброс пароля SQL Server компьютере, а затем сценарий входа.

     Примечание

    При сбросе пароля используется алгоритм хаширования пароля.

  • Метод 2. Перенос логинов и паролей на сервер назначения (Server B) с помощью скриптов, созданных на сервере источника (Server A)
    1. Создайте сохраненные процедуры, которые помогут создать необходимые скрипты для передачи логинов и их паролей. Для этого подключите сервер A с SQL Server Management Studio (SSMS) или любым другим клиентом и запустите следующий скрипт:
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 @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 
          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'
          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 
              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
          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 + ']'
                  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 + ']'

                          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 
      END
      CLOSE login_curs
      DEALLOCATE login_curs
      RETURN 0
  END

Примечание: В этом скрипте создаются две сохраненные процедуры в мастер-базе данных. Процедуры называются sp_hexadecimal и sp_help_revlogin.

  1. В редакторе SSMS запроса выберите параметр Results to Text.
  2. Запустите следующее утверждение в том же или новом окне запроса:
SQL
EXEC sp_help_revlogin

4. Сценарий вывода, который создает sp_help_revlogin сохраненная процедура, — это сценарий входа. Этот сценарий входа создает логины с исходным идентификатором безопасности (SID) и исходным паролем.

Действия на сервере назначения (Сервер B)

Подключение сервер B с помощью любого клиентского средства (например, SSMS), а затем запустите сценарий, созданный в шаге 4 (выход) с sp_helprevlogin сервера A.

Примечания

Просмотрите следующую информацию перед запуском сценария вывода на экземпляре на сервере B:

  • Пароль можно использовать следующими способами:
    • VERSION_SHA1. Этот хаш создается с помощью алгоритма SHA1 и используется в SQL Server 2000 SQL Server 2008 R2.
    • VERSION_SHA2. Этот хаш создается с помощью алгоритма SHA2 512 и используется в SQL Server 2012 и более поздних версиях.
  • Внимательно просмотрите сценарий вывода. Если сервер A и сервер B находятся в разных доменах, необходимо изменить сценарий вывода. Затем необходимо заменить исходное доменное имя с помощью нового доменного имени в заявлениях CREATE LOGIN. Интегрированные логины, которые получили доступ в новом домене, не имеют того же СИД, что и логины в исходном домене. Таким образом, пользователи не могут зайти в систему из этих логинов. Дополнительные сведения о том, как устранить этих осиротевших пользователей, см. в выпуске How to resolve permission issues when you move a database between servers that are running SQL Server.

    Если сервер A и сервер B находятся в одном домене, используется один и тот же SID. Поэтому пользователи вряд ли будут осиротеть.

  • В сценарии вывода логины создаются с помощью зашифрованного пароля. Это из-за аргумента HASHED в CREATE LOGIN заявлении. В этом аргументе указывается, что пароль, который вошел после того, как аргумент PASSWORD уже имеется.
  • По умолчанию только член роли фиксированного сервера sysadmin может запускать заявление SELECT из sys.server_principals представления. Если участник роли фиксированного сервера sysadmin не предоставляет пользователям необходимые разрешения, пользователи не могут создавать и запускать сценарий вывода.
  • Действия в этой статье не передают данные базы данных по умолчанию для определенного входа. Это происходит из-за того, что база данных по умолчанию может не всегда существовать на сервере B. Чтобы определить базу данных по умолчанию для входа, используйте заявление, передав имя входа и базу данных по умолчанию ALTER LOGIN в качестве аргументов.
  • Сортировка заказов на исходных и почтовых серверах:
    • Нечувствительный сервер A и сервер B, чувствительный к делу: порядок сортировки сервера A может быть нечувствительным к делу, а порядок сортировки сервера B может быть чувствительным к делу. В этом случае пользователи должны вводить пароли во всех верхних буквах после передачи логинов и паролей экземпляру на сервере B.
    • Чувствительный к делу сервер A и сервер B, нечувствительный к делу: Порядок сортировки сервера A может быть чувствительным к делу, а порядок сортировки сервера B может быть нечувствительным. В этом случае пользователи не могут войти с помощью логинов и паролей, которые вы передаете экземпляру на сервере B, если одно из следующих условий не является верным:
      • Исходные пароли не содержат букв.
      • Все буквы в исходных паролях — это буквы верхнего регистра.
    • Чувствительный к делу или нечувствительный к делу на обоих серверах: порядок сортировки как сервера A, так и сервера B может быть чувствительным к делу, или порядок сортировки как сервера A, так и сервера B может быть нечувствительным к делу. В этих случаях пользователи не испытывают проблем.
  • Вход, который уже находится в экземпляре на сервере B, может иметь имя, такое же, как имя в сценарии вывода. В этом случае при запуске сценария вывода на экземпляре на сервере B вы получите следующее сообщение об ошибке:

    Msg 15025, Level 16, State 1, Line 1
    Принцип сервера ‘MyLogin’ уже существует.

    Кроме того, вход, который уже находится в экземпляре на сервере B, может иметь SID, который является таким же, как SID в сценарии вывода. В этом случае при запуске сценария вывода на экземпляре на сервере B вы получите следующее сообщение об ошибке:

    Msg 15433, Level 16, State 1, Line 1 Supplied parameter sid is in use.

    Поэтому необходимо сделать следующее:

    1. Внимательно просмотрите сценарий вывода.
    2. Изучите содержимое sys.server_principals в экземпляре на сервере B.
    3. Адрес этих сообщений об ошибках по мере необходимости.

      В SQL Server 2005 г. для реализации доступа к базе данных используется SID для входа в систему. В разных базах данных на сервере могут быть разные siD-данные. В этом случае для входа можно получить доступ только к базе данных, которая имеет SID, совпадает с SID в sys.server_principals представлении. Эта проблема может возникнуть, если две базы данных объединены с разных серверов. Чтобы устранить эту проблему, вручную удалите вход из базы данных с несоответствием SID с помощью инструкции DROP USER. Затем снова добавьте вход с помощью CREATE USER этого утверждения.