Transferir logons e senhas entre instâncias do SQL Server
Este artigo descreve como transferir os logons e as senhas entre diferentes instâncias do SQL Server em execução no Windows.
Versão original do produto: SQL Server
Número original do KB: 918992, 246133
Introdução
Este artigo descreve como transferir os logons e senhas entre diferentes instâncias do Microsoft SQL Server.
Observação
As instâncias podem estar no mesmo servidor ou em servidores diferentes, e suas versões podem ser diferentes.
Mais informações
Neste artigo, os servidores A e B são servidores diferentes.
Depois de mover um banco de dados da instância do SQL Server no servidor A para a instância do SQL Server no servidor B, os usuários podem não conseguir fazer logon no banco de dados no servidor B. Além disso, os usuários podem receber a seguinte mensagem de erro:
Falha no logon do usuário "MyUser" (Microsoft SQL Server, Erro: 18456)
Esse problema ocorre porque você não transferiu os logons e as senhas da instância do SQL Server no servidor A para a instância do SQL Server no servidor B.
Observação
A mensagem de erro 18456 também ocorre devido a outros motivos. Para obter informações adicionais sobre essas causas e possíveis resoluções, consulte MSSQLSERVER_18456.
Para transferir os logins, use um dos seguintes métodos, conforme apropriado à situação.
Método 1: Redefina a senha no computador SQL Server de destino (Servidor B).
Para resolver esse problema, redefina a senha no computador do SQL Server e, em seguida, faça o script do logon.
Observação
O algoritmo de hash de senha é usado quando você redefine a senha.
Método 2: Transfira logins e senhas para o servidor de destino (Servidor B) usando scripts gerados no servidor de origem (Servidor A).
Crie procedimentos armazenados que ajudarão a gerar scripts necessários para transferir logons e suas senhas. Para fazer isso, conecte-se ao Servidor A usando o SSMS (SQL Server Management Studio) ou qualquer outra ferramenta cliente e execute o seguinte script:
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
Observação
Esse script cria dois procedimentos armazenados no banco de dados mestre. Os procedimentos são denominados sp_hexadecimal e sp_help_revlogin.
No editor de consultas do SSMS, selecione a opção Resultados em Texto.
Execute a seguinte instrução na mesma janela ou em uma nova janela de consulta:
EXEC sp_help_revlogin
O script de saída gerado pelo procedimento
sp_help_revlogin
armazenado é o script de logon. Esse script de logon cria os logons que têm o SID (Identificador de Segurança) original e a senha original.
Importante
Examine as informações na seção Comentários a seguir antes de prosseguir com a implementação de etapas no servidor de destino.
Etapas no servidor de destino (Servidor B)
Conecte-se ao Servidor B usando qualquer ferramenta cliente (como SSMS) e execute o script gerado na etapa 4 (saída de sp_helprevlogin
) do Servidor A.
Comentários
Examine as seguintes informações antes de executar o script de saída na instância no servidor B:
Uma senha pode ter hash das seguintes maneiras:
VERSION_SHA1
: esse hash é gerado usando o algoritmo SHA1 e é usado no SQL Server 2000 ao SQL Server 2008 R2.VERSION_SHA2
: esse hash é gerado usando o algoritmo SHA2 512 e é usado no SQL Server 2012 e versões posteriores.
Examine o script de saída com cuidado. Se o servidor A e o servidor B estão em domínios diferentes, você precisa alterar o script de saída. Em seguida, você deve substituir o nome de domínio original usando o
CREATE LOGIN
novo nome de domínio nas instruções. Os logons integrados que recebem acesso no novo domínio não têm o mesmo SID que os logons no domínio original. Portanto, os usuários são órfãos desses logons. Para obter mais informações sobre como resolver esses usuários órfãos, consulte Solucionar problemas de usuários órfãos (SQL Server) e ALTER USER.
Se o servidor A e o servidor B estão no mesmo domínio, o mesmo SID é usado. Portanto, é improvável que os usuários sejam órfãos.No script de saída, os logons são criados usando a senha criptografada. Isso ocorre devido ao argumento HASHED na instrução
CREATE LOGIN
. Esse argumento especifica que a senha inserida após o argumento PASSWORD já esteja com hash.Por padrão, somente um membro da função de servidor fixo sysadmin pode executar uma instrução
SELECT
da exibiçãosys.server_principals
. A menos que um membro da função de servidor fixa sysadmin conceda as permissões necessárias aos usuários, os usuários não poderão criar ou executar o script de saída.As etapas neste artigo não transferem as informações do banco de dados padrão para um logon específico. Isso ocorre porque o banco de dados padrão pode nem sempre existir no servidor B. Para definir o banco de dados padrão para um logon, use a
ALTER LOGIN
instrução passando o nome de logon e o banco de dados padrão como argumentos.Classificar pedidos em servidores de origem e de destino:
Servidor A que não diferencia maiúsculas de minúsculas e servidor B que diferencia maiúsculas de minúsculas: a ordem de classificação do servidor A pode não diferenciar maiúsculas de minúsculas e a ordem de classificação do servidor B pode diferenciar maiúsculas de minúsculas. Nesse caso, os usuários devem digitar as senhas em todas as letras maiúsculas depois que você transferir os logons e as senhas para a instância no servidor B.
Servidor A que diferencia maiúsculas de minúsculas e servidor B que não diferencia maiúsculas de minúsculas: a ordem de classificação do servidor A pode diferenciar maiúsculas de minúsculas e a ordem de classificação do servidor B pode não diferenciar maiúsculas de minúsculas. Nesse caso, os usuários não podem fazer login usando os logons e as senhas que você transfere para a instância no servidor B, a menos que uma das seguintes condições seja verdadeira:
- As senhas originais não contêm letras.
- Todas as letras nas senhas originais são letras maiúsculas.
Diferencia maiúsculas de minúsculas ou não diferencia maiúsculas de minúsculas em ambos os servidores: a ordem de classificação do servidor A e do servidor B pode diferenciar maiúsculas de minúsculas ou a ordem de classificação do servidor A e do servidor B pode não diferenciar maiúsculas de minúsculas. Nesses casos, os usuários não enfrentam problemas.
Um logon que já está na instância no servidor B pode ter um nome igual a um nome no script de saída. Nesse caso, você receberá a seguinte mensagem de erro ao executar o script de saída na instância no servidor B:
Mensagem 15025, Nível 16, Estado 1, Linha 1
A entidade de segurança do servidor 'MyLogin' já existe.Da mesma forma, um logon que já está na instância no servidor B pode ter um SID igual a um SID no script de saída. Nesse caso, você receberá a seguinte mensagem de erro ao executar o script de saída na instância no servidor B:
Msg 15433, Nível 16, Estado 1, Linha 1 Sid de parâmetro fornecido está em uso.
Portanto, você precisa fazer o seguinte:
Examine o script de saída com cuidado.
Examine o
sys.server_principals
conteúdo da exibição na instância no servidor B.Solucione essas mensagens de erro conforme apropriado.
No SQL Server 2005, o SID de um logon é usado para implementar o acesso no nível do banco de dados. Um logon pode ter SIDs diferentes em bancos de dados diferentes em um servidor. Nesse caso, o logon só pode acessar o banco de dados que tem o SID que corresponde ao SID na exibição
sys.server_principals
. Esse problema pode ocorrer se os dois bancos de dados forem combinados de servidores diferentes. Para resolver esse problema, remova manualmente o logon do banco de dados que tem uma incompatibilidade de SID usando a instrução DROP USER. Em seguida, adicione o logon novamente usando a instruçãoCREATE USER
.