O servidor principal não consegue acessar o banco de dados no contexto de segurança atual no SQL Server MS 2012

103

Estou tentando acessar o banco de dados do meu servidor de hospedagem através do SQL Server Management Studio, tudo bem até o login, mas quando uso o comando use myDatabase, ocorre este erro:

The server principal "****" is not able to access the database "****" under the current security context.

Eu pesquisei e os provedores de serviços de hospedagem listaram essa correção para o problema.

Mas isso não está funcionando para mim, provavelmente porque é para SQL Server Management Studio 2008, no entanto, estou usando o SQL Server Management Studio 2012.

Isso pode ser um problema? E se sim, alguém pode me dizer sua alternativa no SSMS 2012?

Maven
fonte
3
'Provedores de serviços de hospedagem'? Estamos falando dedicado ou compartilhado? Se for um servidor de hospedagem compartilhada, recomendo entrar em contato com seu provedor de hospedagem para obter assistência. SQL em um ambiente de hospedagem compartilhada é notoriamente cheio de erros e problemático. Não tem nada a ver com o produto, mas com as políticas que os provedores de hospedagem aplicam ao (s) servidor (es). Cada empresa de hospedagem tem sua própria maneira de alavancar o SQL ou assim parece.
Techie Joe

Respostas:

80

Verifique se o seu usuário está mapeado para o banco de dados no qual você está tentando efetuar login.

Scott
fonte
76
como você faz isso?
Graham,
3
@ Graham Use o SQL Server Management Studio para verificar o usuário ou veja esta resposta: stackoverflow.com/a/9356725/804773
Grambot
5
Eu sugeriria que procurasse triggers, por isso recebi esta mensagem, havia um trigger fazendo alguma coisa em outro banco de dados onde meu usuário não estava autorizado.
DanielV
1
Eu achei o erro do OP e esperei esta resposta, descobri que acabei de ter um erro de digitação estúpido no Nome do Banco de Dados em minha string de conexão conectando-se ao Banco de Dados SQL do Azure. Se o nome do seu banco de dados estiver correto, você não precisa acessar o mestre. Se estiver errado, então (no meu caso) acho que o Entity Framework (6.1.3) está tentando ser mais inteligente conectando-se ao Master para obter algumas informações adicionais (embora isso possa não estar relacionado ao EF - não tenho certeza). Mas minha solução foi ter certeza de que minha cadeia de conexões estava correta. Eu esperava um erro muito diferente para um nome de banco de dados incorreto. : - /
Jaxidian
2
Para adicionar comentários de @DanielV, verifique também os procedimentos armazenados para quaisquer nomes de banco de dados codificados. Corrigido no meu caso (cerca de 20 procedimentos armazenados tiveram que ser alterados).
Demonslay335
26

Tivemos o mesmo erro ao implantar um relatório para SSRS em nosso ambiente PROD. Verificou-se que o problema poderia até ser reproduzido com uma declaração “use”. A solução foi sincronizar novamente a referência da conta GUID do usuário com o banco de dados em questão (ou seja, usando "sp_change_users_login" como faria após restaurar um banco de dados). Um script de ações (orientado por cursor) para ressincronizar todas as contas está anexado:

USE <your database>
GO

-------- Reset SQL user account guids ---------------------
DECLARE @UserName nvarchar(255) 
DECLARE orphanuser_cur cursor for 
      SELECT UserName = su.name 
      FROM sysusers su
      JOIN sys.server_principals sp ON sp.name = su.name
      WHERE issqluser = 1 AND
            (su.sid IS NOT NULL AND su.sid <> 0x0) AND
            suser_sname(su.sid) is null 
      ORDER BY su.name 

OPEN orphanuser_cur 
FETCH NEXT FROM orphanuser_cur INTO @UserName 

WHILE (@@fetch_status = 0)
BEGIN 
--PRINT @UserName + ' user name being resynced' 
exec sp_change_users_login 'Update_one', @UserName, @UserName 
FETCH NEXT FROM orphanuser_cur INTO @UserName 
END 

CLOSE orphanuser_cur 
DEALLOCATE orphanuser_cur
Anônimo
fonte
2
Funcionou para mim, obrigado. Copiei um banco de dados com autenticação de servidor SQL para meu servidor de teste e estava inacessível. Agora é
MikeH
1
Se o usuário existe no banco de dados, mas não consegue persistir um mapeamento para o login, deletar esse usuário via SSMS Object Explorer e, em seguida, remapear o login funcionou para mim. Caso contrário, suspeito que a solução proposta acima precisaria ser tomada.
jjt
10

Passei um bom tempo lutando com esse problema e então percebi que estava cometendo um erro simples no fato de ter esquecido para qual banco de dados específico estava direcionando minha conexão. Eu estava usando a janela de conexão padrão do SQL Server para inserir as credenciais:

Janela de conexão do SQL Server

Tive que verificar a guia Propriedades da conexão para verificar se estava escolhendo o banco de dados correto para me conectar. Eu acidentalmente deixei a opção Conectar ao banco de dados aqui definida como uma seleção de uma sessão anterior. É por isso que não consegui me conectar ao banco de dados ao qual pensei que estava tentando me conectar.

Propriedades de conexão

Observe que você precisa clicar no Options >>botão para que as Propriedades da conexão e outras guias apareçam.

Phil Ringsmuth
fonte
10

Isso funcionou para mim:

use <Database>
EXEC  sp_change_users_login @Action='update_one', @UserNamePattern='<userLogin>',@LoginName='<userLogin>';

O problema pode ser visualizado com:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';
Azak
fonte
2
Isso consertou para mim. Obrigado ! "O problema pode ser visualizado com" -> Se eles retornarem um hash diferente, há um problema e a consulta acima irá sincronizá-los.
antes de
7

Logins SQL são definidos no nível do servidor e devem ser mapeados para Usuários em bancos de dados específicos.

No explorador de objetos SSMS, no servidor que você deseja modificar, expanda Segurança > Logins e clique duas vezes no usuário apropriado que abrirá a caixa de diálogo "Propriedades de Login".

Selecione User Mapping , que irá mostrar todos os bancos de dados no servidor, com aqueles que possuem um mapeamento existente selecionado. A partir daqui, você pode selecionar bancos de dados adicionais (e certifique-se de selecionar quais funções em cada banco de dados o usuário deve pertencer) e, em seguida, clicar em OK para adicionar os mapeamentos.

insira a descrição da imagem aqui

Esses mapeamentos podem ser desconectados após uma restauração ou operação semelhante. Nesse caso, o usuário ainda pode existir no banco de dados, mas não está realmente mapeado para um login. Se isso acontecer, você pode executar o seguinte para restaurar o login:

USE {database};
ALTER USER {user} WITH login = {login}

Você também pode excluir o usuário do banco de dados e recriá-lo na caixa de diálogo Propriedades de login, mas quaisquer associações de função ou outras configurações precisariam ser recriadas.

Tobias J
fonte
4

No meu caso, a mensagem foi causada por um sinônimo que incluía inadvertidamente o nome do banco de dados no "nome do objeto". Quando restaurei o banco de dados com um novo nome, o sinônimo ainda apontava para o antigo nome do banco de dados. Como o usuário não tinha permissões no BD antigo, a mensagem apareceu. Para corrigir, eliminei e recriei o sinônimo sem qualificar o nome do objeto com o nome do banco de dados:

    USE [new_db]
GO

/****** Object:  Synonym [dbo].[synTable]    Script Date: 10/15/2015 9:45:01 AM ******/
DROP SYNONYM [dbo].[synTable]
GO

/****** Object:  Synonym [dbo].[synTable]    Script Date: 10/15/2015 9:45:01 AM ******/
CREATE SYNONYM [dbo].[synTable] FOR [dbo].[tTheRealTable]
GO
Joshua Yeidel
fonte
2

Ocorreu o mesmo erro, embora o usuário tenha sido mapeado corretamente para o login.

Após tentar excluir o usuário, foi descoberto que alguns SPs continham "com execute como" aquele usuário.

O problema foi resolvido descartando esses SPs, descartando o usuário, recriando o usuário vinculado ao login e recriando os SPs.

Possivelmente, ele entrou nesse estado ao restaurar do backup (durante um tempo em que o login relacionado não existia) ou ao sincronizar o esquema em massa (se for possível criar um SP com execute como mesmo que o usuário não exista. foi relacionado a esta resposta .

crokusek
fonte
1
Você pode explicar o que entende por SPs?
Scuba Steve
1
Procedimento armazenado. Ao criar um SP (criar proc xxx ...), há uma cláusula opcional "com execute como <usuário>" que especifica que o SP será executado como se aquele usuário o tivesse executado em vez do usuário conectado no momento.
crokusek
1

Encontrei o mesmo erro ao usar Server Management Objects (SMO) em vb.net (tenho certeza que é o mesmo em C #)

O comentário de Techie Joe na postagem inicial foi um aviso útil de que na hospedagem compartilhada muitas coisas adicionais estão acontecendo. Demorou um pouco para descobrir, mas o código a seguir mostra como é preciso ser muito específico na forma de acessar os bancos de dados SQL. O erro 'principal do servidor ...' parecia aparecer sempre que as chamadas SMO não eram precisamente específicas no ambiente de hospedagem compartilhada.

Esta primeira seção do código foi contra um servidor SQL Express local e contou com a autenticação simples do Windows. Todos os códigos usados ​​nesses exemplos são baseados no tutorial SMO de Robert Kanasz neste artigo do site do Projeto de código :

  Dim conn2 = New ServerConnection()
  conn2.ServerInstance = "<local pc name>\SQLEXPRESS"
  Try
    Dim testConnection As New Server(conn2)
    Debug.WriteLine("Server: " + testConnection.Name)
    Debug.WriteLine("Edition: " + testConnection.Information.Edition)
    Debug.WriteLine(" ")

    For Each db2 As Database In testConnection.Databases
      Debug.Write(db2.Name & " - ")
      For Each fg As FileGroup In db2.FileGroups
        Debug.Write(fg.Name & " - ")
        For Each df As DataFile In fg.Files
          Debug.WriteLine(df.Name + " - " + df.FileName)
        Next
      Next
    Next
    conn2.Disconnect()

  Catch err As Exception
    Debug.WriteLine(err.Message)
  End Try

O código acima encontra os arquivos .mdf para cada banco de dados no servidor SQLEXPRESS local perfeitamente porque a autenticação é controlada pelo Windows e é ampla em todos os bancos de dados.

No código a seguir, há 2 seções iterando para os arquivos .mdf. Nesse caso, apenas a primeira iteração à procura de um grupo de arquivos funciona e só encontra um único arquivo, pois a conexão é feita com apenas um único banco de dados no ambiente de hospedagem compartilhado.

A segunda iteração, que é uma cópia da iteração que funcionou acima, bloqueia imediatamente porque da forma como está escrita tenta acessar a 1ª base de dados do ambiente compartilhado, que não é aquele ao qual se aplica o User ID / Password, portanto o servidor SQL retorna um erro de autorização na forma do erro 'principal do servidor ...'.

Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection
sqlConnection1.ConnectionString = "connection string with User ID/Password to a specific database in a shared hosting system. This string will likely also include the Data Source and Initial Catalog parameters"
Dim conn1 As New ServerConnection(sqlConnection1)
Try
  Dim testConnection As New Server(conn1)
  Debug.WriteLine("Server: " + testConnection.Name)
  Debug.WriteLine("Edition: " + testConnection.Information.Edition)
  Debug.WriteLine(" ")

  Dim db2 = testConnection.Databases("the name of the database to which the User ID/Password in the connection string applies")
  For Each fg As FileGroup In db2.FileGroups
    Debug.Write(fg.Name & " - ")
    For Each df As DataFile In fg.Files
      Debug.WriteLine(df.Name + " - " + df.FileName)
    Next
  Next

  For Each db3 As Database In testConnection.Databases
    Debug.Write(db3.Name & " - ")
    For Each fg As FileGroup In db3.FileGroups
      Debug.Write(fg.Name & " - ")
      For Each df As DataFile In fg.Files
        Debug.WriteLine(df.Name + " - " + df.FileName)
      Next
    Next
  Next

  conn1.Disconnect()

Catch err As Exception
  Debug.WriteLine(err.Message)
End Try

Nesse segundo loop de iteração, o código compila bem, mas como o SMO não foi configurado para acessar precisamente o banco de dados correto com a sintaxe precisa, essa tentativa falha.

Como estou aprendendo o SMO, achei que outros novatos gostariam de saber que há uma explicação mais simples para esse erro - apenas codificamos errado.

Alan
fonte
0

Eu acredito que você pode estar faltando uma instrução "Grant Connect To" quando você criou o usuário do banco de dados.

Abaixo está o snippet completo de que você precisará para criar um login no DBMS do SQL Server e um usuário no banco de dados

USE [master]
GO

CREATE LOGIN [SqlServerLogin] WITH PASSWORD=N'Passwordxyz', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
GO

USE [myDatabase]
GO

CREATE USER [DatabaseUser] FOR LOGIN [SqlServerLogin] WITH DEFAULT_SCHEMA=[mySchema]
GO

GRANT CONNECT TO [DatabaseUser]
GO

-- the role membership below will allow you to run a test "select" query against the tables in your database
ALTER ROLE [db_datareader] ADD MEMBER [DatabaseUser]
GO
Salim Gangji
fonte