L'entità server non è in grado di accedere al database nel contesto di sicurezza corrente in SQL Server MS 2012


103

Sto cercando di accedere al database del mio server di hosting tramite SQL Server Management Studio, tutto fino al login va bene ma quando uso il comando use myDatabasemi dà questo errore:

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

Ho cercato più volte e il provider di servizi di hosting ha elencato questa soluzione per il problema.

Ma questo non funziona per me probabilmente perché è per SQL Server Management Studio 2008, tuttavia sto usando SQL Server Management Studio 2012.

Può essere un problema? E se sì, qualcuno può dirmi la sua alternativa in SSMS 2012?


3
"Fornitori di servizi di hosting"? Stiamo parlando dedicato o condiviso? Se si tratta di un server di hosting condiviso, consiglio vivamente di contattare il tuo provider di hosting per assistenza. SQL in un ambiente di hosting condiviso è notoriamente buggato e problematico. Non ha nulla a che fare con il prodotto, ma con le politiche che i provider di hosting applicano ai server. Ogni società di hosting ha il proprio modo di sfruttare SQL o almeno così sembra.
Techie Joe,

Risposte:


80

Controlla se il tuo utente è mappato al DB a cui stai tentando di accedere.


76
Come si fa a farlo?
Graham

3
@Graham O utilizzare SQL Server Management Studio per controllare l'utente oppure vedere questa risposta: stackoverflow.com/a/9356725/804773
Grambot

5
Suggerirei di cercare i trigger, questo è il motivo per cui ho ricevuto questo messaggio, c'era un trigger che faceva alcune cose in un altro database in cui il mio utente non era autorizzato.
DanielV

1
Ho colpito l'errore dell'OP e grazie a questa risposta, ho capito di aver appena avuto uno stupido errore di battitura nel nome del database nella mia stringa di connessione che si connette al database SQL di Azure. Se il nome del database è corretto, non è necessario accedere a Master. Se è sbagliato, allora (nel mio caso) penso che Entity Framework (6.1.3) stia cercando di essere più intelligente collegandosi a Master per alcune informazioni aggiuntive (anche se potrebbe non essere correlato a EF - non ne sono sicuro). Ma la mia soluzione era assicurarmi che la mia stringa di connessione fosse corretta. Mi aspettavo un errore molto diverso per un nome di database errato. : - /
Jaxidian

2
Per aggiungere al commento di @DanielV, controlla anche Stored Procedures per eventuali nomi di database codificati. Risolto il problema nel mio caso (è stato necessario modificare circa 20 stored procedure).
Demonslay335

26

Si è verificato lo stesso errore durante la distribuzione di un report a SSRS nel nostro ambiente PROD. Si è riscontrato che il problema poteva anche essere riprodotto con un'istruzione "use". La soluzione consisteva nel risincronizzare il riferimento dell'account GUID dell'utente con il database in questione (ovvero, utilizzando "sp_change_users_login" come si farebbe dopo il ripristino di un database). È allegato uno script stock (guidato dal cursore) per risincronizzare tutti gli account:

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

2
Ha funzionato per me Grazie. Avevo copiato un database con un'autenticazione del server SQL sul mio server di prova ed era inaccessibile. Ora è
MikeH

1
Se l'utente esiste nel database ma non riesce a persistere una mappatura al login, l'eliminazione di detto utente tramite SSMS Object Explorer e quindi la rimappatura del login ha funzionato per me. Altrimenti, sospetto che la soluzione proposta sopra dovrebbe essere presa.
jjt

10

Ho passato un bel po 'di tempo a lottare con questo problema e poi mi sono reso conto che stavo facendo un semplice errore nel fatto che avevo dimenticato a quale database particolare stavo indirizzando la mia connessione. Stavo usando la finestra di connessione standard di SQL Server per inserire le credenziali:

Finestra di connessione a SQL Server

Ho dovuto controllare la scheda Proprietà connessione per verificare che stavo scegliendo il database corretto a cui connettermi. Avevo lasciato accidentalmente l' opzione Connetti al database qui impostata su una selezione di una sessione precedente. Questo è il motivo per cui non sono riuscito a connettermi al database a cui pensavo di provare a connettermi.

Proprietà di connessione

Si noti che è necessario fare clic sul Options >>pulsante per visualizzare le proprietà di connessione e altre schede.


10

Questo ha funzionato per me:

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

Il problema può essere visualizzato con:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';

2
Questo ha risolto il problema per me. Grazie ! "Il problema può essere visualizzato con" -> Se restituiscono un hash diverso, c'è un problema e la query sopra li sincronizzerà.
prima del

7

Gli accessi SQL sono definiti a livello di server e devono essere mappati agli utenti in database specifici.

In SSMS Object Explorer, sotto il server che si desidera modificare, espandere Protezione > Login , quindi fare doppio clic sull'utente appropriato che farà apparire la finestra di dialogo "Proprietà di accesso".

Seleziona Mappatura utente , che mostrerà tutti i database sul server, con quelli con una mappatura esistente selezionata. Da qui è possibile selezionare database aggiuntivi (e assicurarsi di selezionare i ruoli in ciascun database a cui deve appartenere l'utente), quindi fare clic su OK per aggiungere le mappature.

inserisci qui la descrizione dell'immagine

Queste mappature possono essere disconnesse dopo un ripristino o un'operazione simile. In questo caso, l'utente può ancora esistere nel database ma non è effettivamente mappato a un account di accesso. In tal caso, è possibile eseguire quanto segue per ripristinare l'accesso:

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

È inoltre possibile eliminare l'utente DB e ricrearlo dalla finestra di dialogo Proprietà di accesso, ma è necessario ricreare eventuali appartenenze ai ruoli o altre impostazioni.


4

Nel mio caso, il messaggio è stato causato da un sinonimo che inavvertitamente ha incluso il nome del database nel "nome oggetto". Quando ho ripristinato il database con un nuovo nome, il sinonimo puntava ancora al vecchio nome DB. Poiché l'utente non disponeva dei permessi nel vecchio DB, è apparso il messaggio. Per risolvere il problema, ho eliminato e ricreato il sinonimo senza qualificare il nome dell'oggetto con il nome del database:

    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

2

Si è verificato lo stesso errore anche se l'utente era stato correttamente mappato al login.

Dopo aver tentato di eliminare l'utente, è stato scoperto che alcuni SP contenevano "con esegui come" quell'utente.

Il problema è stato risolto eliminando quegli SP, eliminando l'utente, ricreando l'utente collegato al login e ricreando gli SP.

Probabilmente è entrato in questo stato dal ripristino dal backup (durante un periodo in cui il relativo login non esisteva) o dalla sincronizzazione in blocco dello schema (se è possibile creare un SP con execute anche se l'utente non esiste. Potrebbe anche avere stato correlato a questa risposta .


1
Puoi approfondire cosa intendi per SP?
Scuba Steve

1
Procedura memorizzata. Quando si crea un SP (create proc xxx ...), c'è una clausola opzionale "con esegui come <utente>" che specifica che l'SP verrà eseguito come se quell'utente lo avesse eseguito al posto dell'utente attualmente connesso.
crokusek

1

Ho riscontrato lo stesso errore durante l'utilizzo di Server Management Objects (SMO) in vb.net (sono sicuro che sia lo stesso in C #)

Il commento di Techie Joe sul post iniziale è stato un utile avvertimento che nell'hosting condiviso stanno accadendo molte cose aggiuntive. Ci è voluto un po 'di tempo per capirlo, ma il codice seguente mostra come bisogna essere molto specifici nel modo in cui si accede ai database SQL. L'errore "server principal ..." sembrava comparire ogni volta che le chiamate SMO non erano precisamente specifiche nell'ambiente di hosting condiviso.

Questa prima sezione di codice era relativa a un server SQL Express locale e si basava su una semplice autenticazione di Windows. Tutto il codice utilizzato in questi esempi si basa sul tutorial SMO di Robert Kanasz in questo articolo del sito Web di 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

Il codice sopra trova i file .mdf per ogni database sul server SQLEXPRESS locale correttamente perché l'autenticazione è gestita da Windows ed è ampia in tutti i database.

Nel codice seguente ci sono 2 sezioni che iterano per i file .mdf. In questo caso funziona solo la prima iterazione alla ricerca di un filegroup e trova solo un singolo file perché la connessione è a un solo database nell'ambiente di hosting condiviso.

La seconda iterazione, che è una copia dell'iterazione che ha funzionato sopra, si blocca immediatamente perché per come è scritta cerca di accedere al 1 ° database nell'ambiente condiviso, che non è quello a cui si applicano User ID / Password, quindi il server SQL restituisce un errore di autorizzazione sotto forma di errore "server 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

In quel secondo ciclo di iterazione, il codice si compila bene, ma poiché SMO non è stato configurato per accedere esattamente al database corretto con la sintassi precisa, quel tentativo fallisce.

Dato che sto solo imparando SMO, ho pensato che altri neofiti potrebbero apprezzare il fatto che ci sia anche una spiegazione più semplice per questo errore: l'abbiamo semplicemente codificato in modo sbagliato.


0

Credo che potresti perdere un'istruzione "Concedi connessione a" quando hai creato l'utente del database.

Di seguito è riportato lo snippet completo di cui avrai bisogno per creare sia un accesso sul DBMS di SQL Server sia un utente sul database

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.