Le principal du serveur ne peut pas accéder à la base de données dans le contexte de sécurité actuel dans SQL Server MS 2012

103

J'essaie d'accéder à la base de données de mon serveur d'hébergement via SQL Server Management Studio, tout jusqu'à la connexion va bien, mais lorsque j'utilise la commande, use myDatabasecela me donne cette erreur:

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

J'ai cherché et les fournisseurs de services d'hébergement ont répertorié ce correctif pour le problème.

Mais cela ne fonctionne pas pour moi probablement parce que c'est pour SQL Server Management Studio 2008, mais j'utilise SQL Server Management Studio 2012.

Cela peut-il être un problème? Et si oui, que quelqu'un peut-il me dire son alternative dans SSMS 2012?

Maven
la source
3
«Fournisseurs de services d'hébergement»? Parlons-nous dédié ou partagé? S'il s'agit d'un serveur d'hébergement partagé, je vous recommande vivement de contacter votre fournisseur d'hébergement pour obtenir de l'aide. SQL dans un environnement d'hébergement partagé est notoirement bogué et problématique. Cela n'a rien à voir avec le produit mais les politiques que les fournisseurs d'hébergement appliquent au (x) serveur (s). Chaque société d'hébergement a sa propre façon d'exploiter SQL ou du moins il semble.
Techie Joe

Réponses:

80

Vérifiez si votre utilisateur est mappé à la base de données à laquelle vous essayez de vous connecter.

Scott
la source
76
comment tu fais ça?
Graham
3
@Graham Utilisez SQL Server Management Studio pour vérifier l'utilisateur ou consultez cette réponse: stackoverflow.com/a/9356725/804773
Grambot
5
Je suggérerais de rechercher des déclencheurs, c'est la raison pour laquelle j'ai reçu ce message, il y avait un déclencheur faisant des choses dans une autre base de données où mon utilisateur n'était pas autorisé.
DanielV
1
J'ai frappé l'erreur de l'OP et les réservoirs à cette réponse, j'ai compris que je venais d'avoir une faute de frappe stupide dans le nom de la base de données dans ma chaîne de connexion se connectant à Azure SQL Database. Si votre nom de base de données est correct, vous n'avez pas besoin d'accéder à Master. Si c'est faux, alors (dans mon cas) je pense qu'Entity Framework (6.1.3) essaie d'être très intelligent en se connectant à Master pour obtenir des informations supplémentaires (bien que cela puisse simplement être sans rapport avec EF - je ne suis pas sûr). Mais ma solution était de m'assurer que ma chaîne de connexion était correcte. Je m'attendais à une erreur très différente pour un mauvais nom de base de données. : - /
Jaxidian
2
Pour ajouter au commentaire de @ DanielV, vérifiez également les procédures stockées pour tous les noms de base de données codés en dur. Correction du problème dans mon cas (environ 20 procédures stockées devaient être modifiées).
Demonslay335
26

Nous avons eu la même erreur lors du déploiement d'un rapport vers SSRS dans notre environnement PROD. Il a été constaté que le problème pouvait même être reproduit avec une déclaration «d'utilisation». La solution était de resynchroniser la référence du compte GUID de l'utilisateur avec la base de données en question (c'est-à-dire en utilisant "sp_change_users_login" comme vous le feriez après la restauration d'une base de données). Un script de stock (piloté par le curseur) pour resynchroniser tous les comptes est joint:

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
Anonyme
la source
2
A travaillé pour moi Merci. J'avais copié une base de données avec une authentification de serveur SQL sur mon serveur de test et elle était inaccessible. Maintenant c'est
MikeH
1
Si l'utilisateur existe dans la base de données mais ne parvient pas à conserver un mappage vers la connexion, la suppression dudit utilisateur via l'explorateur d'objets SSMS, puis le remappage de la connexion a fonctionné pour moi. Sinon, je soupçonne que la solution proposée ci-dessus devrait être prise.
jjt
10

J'ai passé pas mal de temps à me débattre avec ce problème, puis j'ai réalisé que je faisais une simple erreur dans le fait que j'avais oublié à quelle base de données je visais ma connexion. J'utilisais la fenêtre de connexion standard de SQL Server pour entrer les informations d'identification:

Fenêtre de connexion SQL Server

J'ai dû vérifier l' onglet Propriétés de connexion pour vérifier que je choisissais la bonne base de données à laquelle me connecter. J'avais accidentellement laissé l' option Se connecter à la base de données ici définie sur une sélection d'une session précédente. C'est pourquoi je n'ai pas pu me connecter à la base de données à laquelle je pensais essayer de me connecter.

Propriétés de connexion

Notez que vous devez cliquer sur le Options >>bouton pour que les propriétés de connexion et les autres onglets s'affichent.

Phil Ringsmuth
la source
10

Cela a fonctionné pour moi:

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

Le problème peut être visualisé avec:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';
azak
la source
2
Cela a réglé le problème pour moi. Merci ! "Le problème peut être visualisé avec" -> S'ils renvoient un hachage différent, il y a un problème et la requête ci-dessus les synchronisera.
bezout le
7

Les connexions SQL sont définies au niveau du serveur et doivent être mappées aux utilisateurs dans des bases de données spécifiques.

Dans l'explorateur d'objets SSMS, sous le serveur que vous souhaitez modifier, développez Sécurité > Connexions , puis double-cliquez sur l'utilisateur approprié qui fera apparaître la boîte de dialogue "Propriétés de connexion".

Sélectionnez User Mapping , qui affichera toutes les bases de données sur le serveur, avec celles ayant un mappage existant sélectionné. À partir de là, vous pouvez sélectionner des bases de données supplémentaires (et assurez-vous de sélectionner les rôles dans chaque base de données auxquels l'utilisateur doit appartenir), puis cliquez sur OK pour ajouter les mappages.

entrez la description de l'image ici

Ces mappages peuvent être déconnectés après une restauration ou une opération similaire. Dans ce cas, l'utilisateur peut toujours exister dans la base de données mais n'est pas réellement mappé à une connexion. Si cela se produit, vous pouvez exécuter ce qui suit pour restaurer la connexion:

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

Vous pouvez également supprimer l'utilisateur de base de données et le recréer à partir de la boîte de dialogue Propriétés de connexion, mais toute appartenance à un rôle ou autre paramètre doit être recréé.

Tobias J
la source
4

Dans mon cas, le message a été causé par un synonyme qui a inclus par inadvertance le nom de la base de données dans le "nom d'objet". Lorsque j'ai restauré la base de données sous un nouveau nom, le synonyme indiquait toujours l'ancien nom de la base de données. Étant donné que l'utilisateur ne disposait pas d'autorisations dans l'ancienne base de données, le message est apparu. Pour corriger, j'ai supprimé et recréé le synonyme sans qualifier le nom de l'objet avec le nom de la base de données:

    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
la source
2

Nous avons eu la même erreur même si l'utilisateur était correctement mappé à la connexion.

Après avoir essayé de supprimer l'utilisateur, on a découvert que quelques SP contenaient "avec exécuter en tant que" cet utilisateur.

Le problème a été résolu en supprimant ces SP, en supprimant l'utilisateur, en recréant l'utilisateur lié à la connexion et en recréant les SP.

Il est peut-être passé dans cet état après une restauration à partir d'une sauvegarde (pendant une période où la connexion associée n'existait pas) ou une synchronisation de schéma en bloc (s'il est possible de créer un SP avec exécuter comme même si l'utilisateur n'existe pas. été liée à cette réponse .

crokusek
la source
1
Pouvez-vous expliquer ce que vous entendez par SP?
Scuba Steve
1
Procédure stockée. Lors de la création d'un SP (create proc xxx ...), il existe une clause facultative "with execute as <user>" qui spécifie que le SP fonctionnera comme si cet utilisateur l'avait exécuté au lieu de l'utilisateur actuellement connecté.
crokusek
1

J'ai rencontré la même erreur lors de l'utilisation d'objets de gestion de serveur (SMO) dans vb.net (je suis sûr que c'est la même chose en C #)

Le commentaire de Techie Joe sur le message initial était un avertissement utile que dans l'hébergement partagé, il se passe beaucoup de choses supplémentaires. Il a fallu un peu de temps pour comprendre, mais le code ci-dessous montre comment il faut être très spécifique dans la façon dont ils accèdent aux bases de données SQL. L'erreur «serveur principal ...» semblait apparaître chaque fois que les appels SMO n'étaient pas précisément spécifiques à l'environnement d'hébergement partagé.

Cette première section de code était basée sur un serveur SQL Express local et reposait sur une simple authentification Windows. Tout le code utilisé dans ces exemples est basé sur le didacticiel SMO de Robert Kanasz dans cet article du site Web Code Project :

  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

Le code ci-dessus trouve très bien les fichiers .mdf pour chaque base de données sur le serveur SQLEXPRESS local, car l'authentification est gérée par Windows et elle est étendue à toutes les bases de données.

Dans le code suivant, il y a 2 sections itérant pour les fichiers .mdf. Dans ce cas, seule la première itération à la recherche d'un groupe de fichiers fonctionne et ne trouve qu'un seul fichier car la connexion est à une seule base de données dans l'environnement d'hébergement partagé.

La deuxième itération, qui est une copie de l'itération qui a fonctionné ci-dessus, s'étouffe immédiatement car la façon dont elle est écrite essaie d'accéder à la 1ère base de données dans l'environnement partagé, qui n'est pas celle à laquelle s'applique l'ID utilisateur / mot de passe, donc le serveur SQL renvoie une erreur d'autorisation sous la forme de l'erreur «serveur principal ...».

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

Dans cette deuxième boucle d'itération, le code se compile correctement, mais comme SMO n'a pas été configuré pour accéder précisément à la base de données correcte avec la syntaxe précise, cette tentative échoue.

Alors que j'apprends SMO, je pensais que d'autres débutants pourraient apprécier de savoir qu'il y avait aussi une explication plus simple à cette erreur - nous l'avons juste mal codée.

Alan
la source
0

Je pense qu'il vous manque peut-être une instruction "Grant Connect To" lorsque vous avez créé l'utilisateur de la base de données.

Vous trouverez ci-dessous l'extrait complet dont vous aurez besoin pour créer à la fois une connexion au SGBD SQL Server et un utilisateur à la base de données

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
la source