Der Serverprinzipal kann unter dem aktuellen Sicherheitskontext in SQL Server MS 2012 nicht auf die Datenbank zugreifen

103

Ich versuche, über SQL Server Management Studio auf die Datenbank meines Hosting-Servers zuzugreifen. Bis zur Anmeldung ist alles in Ordnung, aber wenn ich den Befehl verwende use myDatabase, wird folgende Fehlermeldung angezeigt:

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

Ich habe nachgesehen und der Hosting-Dienstleister hat dieses Update für das Problem aufgelistet .

Aber das funktioniert bei mir wahrscheinlich nicht, weil es für SQL Server Management Studio 2008 ist, aber ich verwende SQL Server Management Studio 2012.

Kann das ein Problem sein? Und wenn ja, kann mir jemand die Alternative in SSMS 2012 sagen?

Maven
quelle
3
"Hosting-Dienstleister"? Sprechen wir engagiert oder geteilt? Wenn es sich um einen gemeinsam genutzten Hosting-Server handelt, empfehle ich dringend, sich an Ihren Hosting-Anbieter zu wenden, um Unterstützung zu erhalten. SQL in einer gemeinsam genutzten Hosting-Umgebung ist bekanntermaßen fehlerhaft und problematisch. Es hat nichts mit dem Produkt zu tun, sondern mit den Richtlinien, die die Hosting-Anbieter für die Server anwenden. Jedes Hosting-Unternehmen hat seine eigene Möglichkeit, SQL zu nutzen.
Techie Joe

Antworten:

80

Überprüfen Sie, ob Ihr Benutzer der Datenbank zugeordnet ist, bei der Sie sich anmelden möchten.

Scott
quelle
75
Wie machst du das?
Graham
3
@ Abraham Verwenden Sie entweder SQL Server Management Studio, um den Benutzer zu überprüfen, oder sehen Sie diese Antwort: stackoverflow.com/a/9356725/804773
Grambot
5
Ich würde vorschlagen, nach Triggern zu suchen. Aus diesem Grund habe ich diese Nachricht erhalten. Es gab einen Trigger, der einige Dinge in einer anderen Datenbank ausführte, in der mein Benutzer nicht autorisiert war.
DanielV
1
Ich habe den Fehler des OP und die Antworten auf diese Antwort gefunden. Ich habe herausgefunden, dass ich in meiner Verbindungszeichenfolge, die eine Verbindung zur Azure SQL-Datenbank herstellt, nur einen dummen Tippfehler im Datenbanknamen hatte. Wenn Ihr Datenbankname korrekt ist, benötigen Sie keinen Zugriff auf den Master. Wenn es falsch ist, dann denke ich (in meinem Fall), dass Entity Framework (6.1.3) versucht, besonders intelligent zu sein, indem es eine Verbindung zum Master herstellt, um zusätzliche Informationen zu erhalten (obwohl dies möglicherweise nichts mit EF zu tun hat - ich bin mir nicht sicher). Aber meine Lösung bestand darin, sicherzustellen, dass mein Verbindungsstring korrekt war. Ich habe einen ganz anderen Fehler für einen schlechten Datenbanknamen erwartet. : - /
Jaxidian
2
Überprüfen Sie zum Speichern des Kommentars von @ DanielV auch die gespeicherten Prozeduren auf fest codierte Datenbanknamen. In meinem Fall wurde das Problem behoben (ca. 20 gespeicherte Prozeduren mussten geändert werden).
Demonslay335
26

Wir hatten den gleichen Fehler beim Bereitstellen eines Berichts für SSRS in unserer PROD-Umgebung. Es wurde festgestellt, dass das Problem sogar mit einer "use" -Anweisung reproduziert werden konnte. Die Lösung bestand darin, die GUID-Kontoreferenz des Benutzers erneut mit der betreffenden Datenbank zu synchronisieren (dh "sp_change_users_login" wie nach dem Wiederherstellen einer Datenbank zu verwenden). Ein Aktienskript (cursorgesteuert) zum erneuten Synchronisieren aller Konten ist beigefügt:

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
Anonym
quelle
2
Arbeitete für mich Danke. Ich hatte eine Datenbank mit einer SQL Server-Authentifizierung auf meinen Testserver kopiert und konnte nicht darauf zugreifen. Jetzt ist es
MikeH
1
Wenn der Benutzer in der Datenbank vorhanden ist, aber keine Zuordnung zum Login beibehalten kann, hat das Löschen des Benutzers über den SSMS-Objekt-Explorer und das erneute Zuordnen des Logins für mich funktioniert. Andernfalls vermute ich, dass die oben vorgeschlagene Lösung getroffen werden müsste.
JJT
10

Ich habe eine ganze Weile mit diesem Problem gerungen und dann festgestellt, dass ich einen einfachen Fehler gemacht habe, weil ich vergessen hatte, auf welche bestimmte Datenbank ich meine Verbindung abzielte. Ich habe das Standard-SQL Server-Verbindungsfenster verwendet, um die Anmeldeinformationen einzugeben:

SQL Server-Verbindungsfenster

Ich hatte das überprüfen Verbindungseigenschaften Registerkarte , um zu überprüfen , dass ich die richtige Datenbank wurde die Wahl zu verbinden. Ich hatte versehentlich die Option Mit Datenbank verbinden hier belassen und eine Auswahl aus einer vorherigen Sitzung festgelegt. Das ist , warum ich nicht in der Lage war zu der Datenbank verbinden ich dachte ich eine Verbindung herstellen wollte.

Verbindungseigenschaften

Beachten Sie, dass Sie auf die Options >>Schaltfläche klicken müssen, damit die Verbindungseigenschaften und andere Registerkarten angezeigt werden.

Phil Ringsmuth
quelle
10

Das hat bei mir funktioniert:

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

Das Problem kann visualisiert werden mit:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';
Azak
quelle
2
Das hat es für mich behoben. Vielen Dank ! "Das Problem kann mit visualisiert werden" -> Wenn sie einen anderen Hash zurückgeben, liegt ein Problem vor und die obige Abfrage synchronisiert sie.
bezout
6

SQL- Anmeldungen werden auf Serverebene definiert und müssen Benutzern in bestimmten Datenbanken zugeordnet werden.

In SSMS Objekt - Explorer unter dem Server , den Sie ändern möchten, erweitern Sie Sicherheit > Logins , doppelklicken Sie auf den entsprechenden Benutzer , die den „Login - Eigenschaften“ Dialog aufzurufen.

Wählen Sie Benutzerzuordnung , um alle Datenbanken auf dem Server anzuzeigen, wobei für diejenigen eine vorhandene Zuordnung ausgewählt ist. Von hier aus können Sie zusätzliche Datenbanken auswählen (und sicherstellen, dass Sie auswählen, zu welchen Rollen in jeder Datenbank dieser Benutzer gehören soll), und dann auf OK klicken , um die Zuordnungen hinzuzufügen.

Geben Sie hier die Bildbeschreibung ein

Diese Zuordnungen können nach einer Wiederherstellung oder einem ähnlichen Vorgang getrennt werden. In diesem Fall ist der Benutzer möglicherweise noch in der Datenbank vorhanden, wird jedoch keinem Login zugeordnet. In diesem Fall können Sie Folgendes ausführen, um die Anmeldung wiederherzustellen:

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

Sie können den DB-Benutzer auch löschen und im Dialogfeld Anmeldeeigenschaften neu erstellen. Rollenmitgliedschaften oder andere Einstellungen müssen jedoch neu erstellt werden.

Tobias J.
quelle
4

In meinem Fall wurde die Nachricht durch ein Synonym verursacht, das versehentlich den Datenbanknamen in den "Objektnamen" aufgenommen hat. Als ich die Datenbank unter einem neuen Namen wiederherstellte, zeigte das Synonym immer noch auf den alten DB-Namen. Da der Benutzer keine Berechtigungen in der alten Datenbank hatte, wurde die Meldung angezeigt. Um dies zu beheben, habe ich das Synonym gelöscht und neu erstellt, ohne den Objektnamen mit dem Datenbanknamen zu qualifizieren:

    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
quelle
2

Wir hatten den gleichen Fehler, obwohl der Benutzer dem Login ordnungsgemäß zugeordnet war.

Nach dem Versuch, den Benutzer zu löschen, wurde festgestellt, dass einige SPs "with execute as" dieses Benutzers enthielten.

Das Problem wurde behoben, indem diese SPs gelöscht, der Benutzer gelöscht, der mit der Anmeldung verknüpfte Benutzer neu erstellt und die SPs neu erstellt wurden.

Möglicherweise wurde es in diesem Zustand durch Wiederherstellen aus dem Backup (während einer Zeit, in der die zugehörige Anmeldung nicht vorhanden war) oder durch Synchronisieren des Massenschemas (wenn es möglich ist, einen SP mit Ausführen zu erstellen, obwohl der Benutzer nicht vorhanden ist) erhalten wurde mit dieser Antwort in Verbindung gebracht .

crokusek
quelle
1
Können Sie näher erläutern, was Sie unter SPs verstehen?
Scuba Steve
1
Gespeicherte Prozedur. Beim Erstellen eines SP (create proc xxx ...) gibt es eine optionale Klausel "with execute as <Benutzer>", die angibt, dass der SP so ausgeführt wird, als hätte dieser Benutzer ihn anstelle des aktuell angemeldeten Benutzers ausgeführt.
Crokusek
1

Bei der Verwendung von Server Management Objects (SMO) in vb.net ist der gleiche Fehler aufgetreten (ich bin sicher, dass er in C # identisch ist).

Techie Joes Kommentar zum ersten Beitrag war eine nützliche Warnung, dass beim Shared Hosting viele zusätzliche Dinge vor sich gehen. Es hat ein wenig gedauert, um herauszufinden, aber der folgende Code zeigt, wie genau man auf SQL-Datenbanken zugreifen muss. Der Fehler "Serverprinzipal ..." schien immer dann aufzutreten, wenn die SMO-Aufrufe in der gemeinsam genutzten Hosting-Umgebung nicht genau waren.

Dieser erste Codeabschnitt war gegen einen lokalen SQL Express-Server gerichtet und stützte sich auf die einfache Windows-Authentifizierung. Der gesamte in diesen Beispielen verwendete Code basiert auf dem SMO-Tutorial von Robert Kanasz in diesem Artikel auf der Code Project-Website :

  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

Der obige Code findet die .mdf-Dateien für jede Datenbank auf dem lokalen SQLEXPRESS-Server in Ordnung, da die Authentifizierung von Windows verwaltet wird und sich über alle Datenbanken erstreckt.

Im folgenden Code werden zwei Abschnitte für die MDF-Dateien iteriert. In diesem Fall funktioniert nur die erste Iteration, die nach einer Dateigruppe sucht, und es wird nur eine einzelne Datei gefunden, da die Verbindung nur zu einer einzelnen Datenbank in der gemeinsam genutzten Hosting-Umgebung besteht.

Die zweite Iteration, bei der es sich um eine Kopie der oben beschriebenen Iteration handelt, wird sofort erstickt, da bei der Schreibweise versucht wird, auf die erste Datenbank in der gemeinsam genutzten Umgebung zuzugreifen, für die die Benutzer-ID / das Kennwort nicht gilt Der SQL Server gibt einen Autorisierungsfehler in Form des Fehlers 'Serverprinzipal ...' zurück.

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

In dieser zweiten Iterationsschleife wird der Code einwandfrei kompiliert. Da SMO jedoch nicht für den Zugriff auf die richtige Datenbank mit der genauen Syntax eingerichtet wurde, schlägt dieser Versuch fehl.

Da ich gerade SMO lerne, dachte ich, dass andere Neulinge es zu schätzen wissen, dass es auch eine einfachere Erklärung für diesen Fehler gibt - wir haben ihn einfach falsch codiert.

Alan
quelle
0

Ich glaube, Sie vermissen möglicherweise eine "Grant Connect To" -Anweisung, als Sie den Datenbankbenutzer erstellt haben.

Unten finden Sie das vollständige Snippet, das Sie benötigen, um sowohl eine Anmeldung für das SQL Server-DBMS als auch einen Benutzer für die Datenbank zu erstellen

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
quelle