Olá pessoal,
Boa noite!
Neste post vou falar sobre um erro que ocorre ao tentar utilizar o comando OPENROWSET ou OPENQUERY para acessar dados de um servidor remoto onde o linked server utilizado não tenha um usuário fixo e o usuário da conexão não pertença à role sysadmin, o que representa a maioria dos casos. (mais um erro reportado pelo Henrique Mauri.. kkk)
Msg 7416, Level 16, State 2, Line 22
Access to the remote server is denied because no login-mapping exists.
Esse erro é muito parecido com o cenário de “double hop” que ocorre no Kerberos, onde uma aplicação cliente está no computador 1, o BizTalk RFID está no computador 2, e o recurso que requer as credenciais (como por exemplo, um servidor SQL Server RFIDsink) está no computador 3, mas nesse post vou mostrar uma solução apenas utilizando o SQL Server. Caso você queira se aprofundar na solução do problema utilizando o Kerberos, dê uma lida nesse post.
Simulando o erro no seu ambiente
Uma forma prática de simular esse problema é criando um novo linked server com o parâmetro @useself=N’True’, informando que o mesmo usuário será utilizado nas duas pontas da conexão, que será o usuário atualmente conectado, e depois tentar utilizar esse linked server.
Como já mencionado acima, essa mensagem de erro só aparece quando o usuário que está executando a query NÃO faça parte da role sysadmin e o usuário da conexão esteja utilizando autenticação SQL Server (ao invés da Autenticação Windows).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
---------------------------------- -- CRIAÇÃO DO LINKED SERVER ---------------------------------- USE [master] GO DECLARE @instancia NVARCHAR(200) = N'127.0.0.1\SQL2014' IF ((SELECT COUNT(*) FROM sys.servers WHERE name = @instancia) > 0) EXEC master.dbo.sp_dropserver @server=@instancia, @droplogins='droplogins' EXEC master.dbo.sp_addlinkedserver @server = @instancia, @srvproduct=N'SQL Server' EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=@instancia,@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL ---------------------------------- -- CRIAÇÃO DA TABELA DE TESTES ---------------------------------- SELECT * FROM OPENROWSET('SQLNCLI', 'Server=127.0.0.1;Trusted_Connection=yes;', 'SELECT * FROM Testes.dbo.Teste') AS a |
Como resolver o problema
Pelo que eu citei mais acima, está claro que se o usuário que está realizando a conexão for adicionado à role sysadmin, esse problema irá parar de ocorrer, mas eu nem considero isso uma solução. Conceder privilégios (ainda mais de sysadmin) só para parar mensagens de erro nunca é solução.
Também não sou muito a favor de fixar o usuário e senha no Linked Server, de forma que todos os usuários com acesso ao servidor possam utilizar esse Linked Server de forma irrastreável. Sempre marque a opção “Be made using the login’s current security context” no LinkedServer.
Uma boa solução seria utilizar Autenticação Windows, mas como a equipe de desenvolvimento da empresa onde ocorreu esse problema não iria nem cogitar a hipótese de alterar a autenticação de todas as aplicações para Autenticação Windows, a melhor solução que eu encontrei para esse problema foi criar um novo usuário apenas para utilizações do OPENROWSET e OPENQUERY, com acessos restritos apenas para as consultas realizadas com esses dois comandos (que são bem poucas) e fixar esse usuário e senha no OPENROWSET, ficando dessa forma:
1 2 |
SELECT * FROM OPENROWSET('SQLNCLI', 'server=127.0.0.1\SQL2014;Uid=Usuario_Teste;Pwd=aaa', 'SELECT * FROM Testes.dbo.Teste') AS a |
And that's it, folks!
Se você souber alguma solução diferente para esse problema, deixe sua sugestão nos comentários.
Abraço e até mais!