Jednostka główna serwera nie może uzyskać dostępu do bazy danych w bieżącym kontekście zabezpieczeń w programie SQL Server MS 2012

103

Próbuję uzyskać dostęp do bazy danych mojego serwera hostingowego przez SQL Server Management Studio, wszystko do momentu zalogowania się, ale kiedy używam polecenia use myDatabase, wyświetla mi się następujący błąd:

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

Przeszukałem i dostawcy usług hostingowych wymienili poprawkę dla problemu.

Ale to prawdopodobnie nie działa dla mnie, ponieważ jest to dla SQL Server Management Studio 2008, jednak używam SQL Server Management Studio 2012.

Czy to może być problem? A jeśli tak, to czy ktoś może mi powiedzieć o jego alternatywie w SSMS 2012?

Maven
źródło
3
„Dostawcy usług hostingowych”? Czy rozmawiamy o oddaniu, czy o udostępnieniu Jeśli jest to serwer współdzielony, gorąco polecam skontaktowanie się z dostawcą usług hostingowych w celu uzyskania pomocy. SQL we współdzielonym środowisku hostingowym jest notorycznie błędny i problematyczny. Nie ma to nic wspólnego z produktem, ale zasady, które dostawcy usług hostingowych stosują do serwerów. Każda firma hostingowa ma swój własny sposób wykorzystania SQL, a przynajmniej tak się wydaje.
Techie Joe,

Odpowiedzi:

80

Sprawdź, czy Twój użytkownik jest zmapowany do bazy danych, do której próbujesz się zalogować.

Scott
źródło
76
jak ty to robisz
Graham
3
@Graham Użyj programu SQL Server Management Studio, aby sprawdzić użytkownika, lub zobacz tę odpowiedź: stackoverflow.com/a/9356725/804773
Grambot
5
Sugerowałbym poszukać wyzwalaczy, z tego powodu otrzymałem tę wiadomość, był wyzwalacz wykonujący coś w innej bazie danych, gdzie mój użytkownik nie był autoryzowany.
DanielV,
1
Uderzyłem w błąd OP i zbiorniki na tę odpowiedź, zorientowałem się, że właśnie mam głupią literówkę w nazwie bazy danych w moim ciągu połączenia łączącym się z Azure SQL Database. Jeśli Twoja nazwa bazy danych jest poprawna, nie potrzebujesz dostępu do Master. Jeśli jest źle, to (w moim przypadku) myślę, że Entity Framework (6.1.3) próbuje być wyjątkowo inteligentny, łącząc się z Master w celu uzyskania dodatkowych informacji (chociaż może to być po prostu niezwiązane z EF - nie jestem pewien). Ale moim rozwiązaniem było upewnienie się, że mój łańcuch połączenia jest poprawny. Spodziewałem się zupełnie innego błędu dla złej nazwy bazy danych. : - /
Jaxidian,
2
Aby dodać do komentarza @ DanielV, sprawdź również procedury składowane pod kątem nazw baz danych zakodowanych na stałe. Naprawiono to w moim przypadku (trzeba było zmienić około 20 procedur składowanych).
Demonslay335,
26

Wystąpił ten sam błąd podczas wdrażania raportu do usług SSRS w naszym środowisku PROD. Stwierdzono, że problem można nawet odtworzyć za pomocą oświadczenia o „użyciu”. Rozwiązaniem było ponowne zsynchronizowanie odniesienia do konta GUID użytkownika z daną bazą danych (tj. Przy użyciu „sp_change_users_login”, tak jak po przywróceniu bazy danych). Dołączony jest skrypt giełdowy (sterowany kursorem) do ponownej synchronizacji wszystkich kont:

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
Anonimowy
źródło
2
Pracował dla mnie Dziękuję. Skopiowałem bazę danych z uwierzytelnianiem serwera SQL na mój serwer testowy i była ona niedostępna. Teraz jest
MikeH
1
Jeśli użytkownik istnieje w bazie danych, ale nie udaje mu się utrwalić mapowania do nazwy logowania, usunięcie tego użytkownika za pośrednictwem narzędzia SSMS Object Explorer, a następnie ponowne mapowanie nazwy logowania działało dla mnie. W przeciwnym razie podejrzewam, że należałoby przyjąć rozwiązanie zaproponowane powyżej.
jjt
10

Spędziłem trochę czasu zmagając się z tym problemem, a potem zdałem sobie sprawę, że popełniam prosty błąd polegający na tym, że zapomniałem, do której konkretnej bazy danych celuję moje połączenie. Użyłem standardowego okna połączenia SQL Server, aby wprowadzić poświadczenia:

Okno połączenia z serwerem SQL

Musiałem sprawdzić kartę Właściwości połączenia , aby sprawdzić, czy wybieram odpowiednią bazę danych do połączenia. Przypadkowo zostawiłem tutaj opcję Połącz z bazą danych ustawioną na wybór z poprzedniej sesji. Dlatego nie mogłem połączyć się z bazą danych, z którą myślałem, że próbuję się połączyć.

Właściwości połączenia

Pamiętaj, że musisz kliknąć Options >>przycisk, aby wyświetlić Właściwości połączenia i inne karty.

Phil Ringsmuth
źródło
10

To zadziałało dla mnie:

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

Problem można zwizualizować za pomocą:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';
azak
źródło
2
To naprawiło to dla mnie. Dzięki ! „Problem można zwizualizować za pomocą” -> Jeśli zwrócą inny hash, wystąpił problem i powyższe zapytanie zsynchronizuje je.
bezout
7

Dane logowania SQL są definiowane na poziomie serwera i muszą być mapowane na użytkowników w określonych bazach danych.

W eksploratorze obiektów SSMS, pod serwerem, który chcesz zmodyfikować, rozwiń Security > Logins , a następnie dwukrotnie kliknij odpowiedniego użytkownika, co spowoduje wyświetlenie okna dialogowego „Login Properties”.

Wybierz opcję Mapowanie użytkownika , co spowoduje wyświetlenie wszystkich baz danych na serwerze, z wybranymi istniejącymi mapami. Z tego miejsca możesz wybrać dodatkowe bazy danych (i pamiętaj, aby wybrać role w każdej bazie danych, do której powinien należeć użytkownik), a następnie kliknij przycisk OK, aby dodać mapowania.

wprowadź opis obrazu tutaj

Te mapowania mogą zostać rozłączone po przywróceniu lub podobnej operacji. W takim przypadku użytkownik może nadal istnieć w bazie danych, ale w rzeczywistości nie jest odwzorowany na login. Jeśli tak się stanie, możesz wykonać następujące czynności, aby przywrócić login:

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

Możesz także usunąć użytkownika bazy danych i utworzyć go ponownie w oknie dialogowym Właściwości logowania, ale wszelkie członkostwa w rolach lub inne ustawienia będą musiały zostać odtworzone.

Tobias J.
źródło
4

W moim przypadku wiadomość została spowodowana przez synonim, który nieumyślnie zawarł nazwę bazy danych w „nazwie obiektu”. Kiedy przywróciłem bazę danych pod nową nazwą, synonim nadal wskazywał na starą nazwę bazy danych. Ponieważ użytkownik nie miał uprawnień w starej bazie danych, pojawił się komunikat. Aby to naprawić, porzuciłem i ponownie utworzyłem synonim bez kwalifikowania nazwy obiektu za pomocą nazwy bazy danych:

    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
źródło
2

Wystąpił ten sam błąd, mimo że użytkownik został poprawnie zmapowany do loginu.

Po próbie usunięcia użytkownika odkryto, że kilka SP zawierało „z wykonaniem jako” tego użytkownika.

Problem został rozwiązany przez usunięcie tych SP, upuszczenie użytkownika, odtworzenie użytkownika powiązanego z logowaniem i odtworzenie SP.

Możliwe, że znalazł się w tym stanie z przywracania z kopii zapasowej (w czasie, gdy powiązany login nie istniał) lub masowej synchronizacji schematu (jeśli możliwe jest utworzenie SP z wykonaniem, tak jakby użytkownik nie istniał). były związane z tą odpowiedzią .

crokusek
źródło
1
Czy możesz wyjaśnić, co masz na myśli przez SP?
Scuba Steve
1
Procedura składowana. Podczas tworzenia SP (create proc xxx ...) istnieje opcjonalna klauzula „with execute as <user>”, która określa, że ​​SP będzie działał tak, jakby uruchomił go ten użytkownik zamiast aktualnie zalogowanego użytkownika.
crokusek
1

Napotkałem ten sam błąd podczas korzystania z obiektów zarządzania serwerem (SMO) w vb.net (jestem pewien, że to to samo w C #)

Komentarz Techie Joe do pierwszego posta był przydatnym ostrzeżeniem, że w hostingu współdzielonym dzieje się wiele dodatkowych rzeczy. Zajęło trochę czasu, aby się zorientować, ale poniższy kod pokazuje, jak bardzo trzeba być bardzo szczegółowym w sposobie uzyskiwania dostępu do baz danych SQL. Wydawało się, że błąd „serwer główny ...” pojawiał się za każdym razem, gdy wywołania SMO nie były dokładnie określone we współdzielonym środowisku hostingu.

Ta pierwsza sekcja kodu dotyczyła lokalnego serwera SQL Express i opierała się na prostym uwierzytelnianiu systemu Windows. Cały kod użyty w tych przykładach jest oparty na samouczku SMO Roberta Kanasza w tym artykule w witrynie 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

Powyższy kod wyszukuje pliki .mdf dla każdej bazy danych na lokalnym serwerze SQLEXPRESS, ponieważ uwierzytelnianie jest obsługiwane przez system Windows i jest rozległe we wszystkich bazach danych.

W poniższym kodzie znajdują się 2 sekcje iterujące dla plików .mdf. W tym przypadku działa tylko pierwsza iteracja szukająca grupy plików i znajduje tylko jeden plik, ponieważ połączenie jest tylko z jedną bazą danych we współdzielonym środowisku hostingu.

Druga iteracja, która jest kopią iteracji, która działała powyżej, dławi się natychmiast, ponieważ sposób, w jaki jest napisany, próbuje uzyskać dostęp do pierwszej bazy danych we współdzielonym środowisku, które nie jest tym, do którego ma zastosowanie identyfikator użytkownika / hasło, więc serwer SQL zwraca błąd autoryzacji w postaci błędu „nazwa główna serwera ...”.

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

W tej drugiej pętli iteracji kod kompiluje się dobrze, ale ponieważ SMO nie był skonfigurowany do uzyskiwania dostępu do dokładnie poprawnej bazy danych z dokładną składnią, ta próba kończy się niepowodzeniem.

Ponieważ dopiero uczę się SMO, pomyślałem, że inni nowicjusze mogą docenić, wiedząc, że istnieje również prostsze wyjaśnienie tego błędu - po prostu źle go zakodowaliśmy.

Alan
źródło
0

Wydaje mi się, że podczas tworzenia użytkownika bazy danych może brakować instrukcji „Grant Connect To”.

Poniżej znajduje się pełny fragment, którego będziesz potrzebować, aby utworzyć zarówno login do systemu DBMS SQL Server, jak i użytkownika do bazy danych

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
źródło