El principal del servidor no puede acceder a la base de datos en el contexto de seguridad actual en SQL Server MS 2012

103

Estoy tratando de acceder a la base de datos de mi servidor de alojamiento a través de SQL Server Management Studio, todo hasta que el inicio de sesión está bien, pero cuando uso el comando use myDatabaseme da este error:

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

Busqué y los proveedores de servicios de alojamiento incluyeron esta solución para el problema.

Pero esto no me funciona probablemente porque es para SQL Server Management Studio 2008, sin embargo, estoy usando SQL Server Management Studio 2012.

Puede ser esto un problema? Y si es así, ¿alguien puede decirme su alternativa en SSMS 2012?

Maven
fuente
3
¿'Proveedores de servicios de alojamiento'? ¿Estamos hablando de dedicados o compartidos? Si se trata de un servidor de alojamiento compartido, le recomiendo que se ponga en contacto con su proveedor de alojamiento para obtener ayuda. SQL en un entorno de alojamiento compartido es notoriamente defectuoso y problemático. No tiene nada que ver con el producto, sino con las políticas que los proveedores de hosting aplican a los servidores. Cada empresa de alojamiento tiene su propia forma de aprovechar SQL o eso parece.
Techie Joe

Respuestas:

80

Verifique si su usuario está asignado a la base de datos en la que está intentando iniciar sesión.

Scott
fuente
76
¿Cómo haces eso?
Graham
3
@Graham Utilice SQL Server Management Studio para verificar el usuario o vea esta respuesta: stackoverflow.com/a/9356725/804773
Grambot
5
Sugeriría buscar disparadores, esa fue la razón por la que recibí este mensaje, había un disparador haciendo algunas cosas en otra base de datos donde mi usuario no estaba autorizado.
DanielV
1
Golpeé el error del OP y los tanques a esta respuesta, descubrí que acababa de tener un error tipográfico estúpido en el Nombre de la base de datos en mi cadena de conexión que se conecta a la Base de datos SQL de Azure. Si el nombre de su base de datos es correcto, no necesita acceso a Master. Si está mal, entonces (en mi caso) creo que Entity Framework (6.1.3) está tratando de ser más inteligente al conectarse a Master para obtener información adicional (aunque eso podría no estar relacionado con EF, no estoy seguro). Pero mi solución fue asegurarme de que mi cadena de conexión fuera correcta. Esperaba un error muy diferente para un nombre de base de datos incorrecto. : - /
Jaxidian
2
Para agregar al comentario de @ DanielV, también verifique Procedimientos almacenados para cualquier nombre de base de datos codificado. Lo solucioné en mi caso (se tuvieron que modificar unos 20 procedimientos almacenados).
Demonslay335
26

Tuvimos el mismo error al implementar un informe en SSRS en nuestro entorno PROD. Se encontró que el problema podría incluso reproducirse con una declaración de "uso". La solución fue volver a sincronizar la referencia de la cuenta GUID del usuario con la base de datos en cuestión (es decir, usando "sp_change_users_login" como lo haría después de restaurar una base de datos). Se adjunta una secuencia de comandos de acciones (impulsada por cursor) para volver a sincronizar todas las cuentas:

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
fuente
2
Trabajó para mí Gracias. Había copiado una base de datos con autenticación de servidor SQL en mi servidor de prueba y era inaccesible. Ahora lo es
MikeH
1
Si el usuario existe en la base de datos pero no persiste en una asignación al inicio de sesión, eliminar dicho usuario a través del Explorador de objetos SSMS y luego reasignar el inicio de sesión funcionó para mí. De lo contrario, sospecho que sería necesario adoptar la solución propuesta anteriormente.
jjt
10

Pasé bastante tiempo luchando con este problema y luego me di cuenta de que estaba cometiendo un simple error en el hecho de que había olvidado a qué base de datos en particular estaba apuntando mi conexión. Estaba usando la ventana de conexión estándar de SQL Server para ingresar las credenciales:

Ventana de conexión de SQL Server

Tuve que verificar la pestaña Propiedades de conexión para verificar que estaba eligiendo la base de datos correcta para conectarme. Accidentalmente había dejado la opción Conectar a la base de datos aquí configurada en una selección de una sesión anterior. Es por eso que no pude conectarme a la base de datos a la que pensé que estaba tratando de conectarme.

Propiedades de conexión

Tenga en cuenta que debe hacer clic en el Options >>botón para que aparezcan las Propiedades de conexión y otras pestañas.

Phil Ringsmuth
fuente
10

Esto funcionó para mí:

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

El problema se puede visualizar con:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';
azak
fuente
2
Esto me lo arregló. Gracias ! "El problema se puede visualizar con" -> Si devuelven un hash diferente, hay un problema y la consulta anterior los sincronizará.
bezout
6

Los inicios de sesión SQL se definen a nivel de servidor y deben asignarse a usuarios en bases de datos específicas.

En el explorador de objetos SSMS, debajo del servidor que desea modificar, expanda Seguridad > Inicios de sesión , luego haga doble clic en el usuario apropiado que mostrará el cuadro de diálogo "Propiedades de inicio de sesión".

Seleccione Asignación de usuarios , que mostrará todas las bases de datos en el servidor, con las que tienen una asignación existente seleccionada. Desde aquí puede seleccionar bases de datos adicionales (y asegúrese de seleccionar a qué roles en cada base de datos debe pertenecer el usuario), luego haga clic en Aceptar para agregar las asignaciones.

ingrese la descripción de la imagen aquí

Estas asignaciones pueden desconectarse después de una restauración u operación similar. En este caso, es posible que el usuario todavía exista en la base de datos, pero en realidad no está asignado a un inicio de sesión. Si eso sucede, puede ejecutar lo siguiente para restaurar el inicio de sesión:

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

También puede eliminar el usuario de la base de datos y volver a crearlo desde el cuadro de diálogo Propiedades de inicio de sesión, pero es necesario volver a crear las pertenencias a roles u otras configuraciones.

Tobias J
fuente
4

En mi caso, el mensaje fue causado por un sinónimo que inadvertidamente incluyó el nombre de la base de datos en el "nombre del objeto". Cuando restauré la base de datos con un nuevo nombre, el sinónimo aún apuntaba al nombre antiguo de la base de datos. Dado que el usuario no tenía permisos en la antigua base de datos, apareció el mensaje. Para solucionarlo, eliminé y recreé el sinónimo sin calificar el nombre del objeto con el nombre de la base de datos:

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

Tuvimos el mismo error a pesar de que el usuario estaba correctamente asignado al inicio de sesión.

Después de intentar eliminar al usuario, se descubrió que algunos SP contenían "con ejecutar como" ese usuario.

El problema se resolvió eliminando esos SP, eliminando al usuario, volviendo a crear el usuario vinculado al inicio de sesión y volviendo a crear los SP.

Posiblemente se puso en este estado al restaurar desde la copia de seguridad (durante un tiempo en el que el inicio de sesión relacionado no existía) o la sincronización masiva del esquema (si es posible, crear un SP con ejecutar como aunque el usuario no existe. También podría haber ha sido relacionado con esta respuesta .

crokusek
fuente
1
¿Puede explicar lo que quiere decir con SP?
Scuba Steve
1
Procedimiento almacenado. Al crear un SP (create proc xxx ...), hay una cláusula opcional "con ejecutar como <usuario>" que especifica que el SP se ejecutará como si ese usuario lo hubiera ejecutado en lugar del usuario actualmente conectado.
crokusek
1

Encontré el mismo error al usar Server Management Objects (SMO) en vb.net (estoy seguro de que es el mismo en C #)

El comentario de Techie Joe sobre la publicación inicial fue una advertencia útil de que en el alojamiento compartido están sucediendo muchas cosas adicionales. Tomó un poco de tiempo averiguarlo, pero el código a continuación muestra cómo uno tiene que ser muy específico en la forma en que accede a las bases de datos SQL. El error 'servidor principal ...' parecía aparecer siempre que las llamadas SMO no eran precisamente específicas en el entorno de alojamiento compartido.

Esta primera sección de código fue contra un servidor SQL Express local y se basó en la autenticación de Windows simple. Todo el código utilizado en estos ejemplos se basa en el tutorial SMO de Robert Kanasz en este artículo del sitio web de 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

El código anterior encuentra los archivos .mdf para cada base de datos en el servidor SQLEXPRESS local muy bien porque la autenticación es manejada por Windows y es amplia en todas las bases de datos.

En el siguiente código hay 2 secciones que se repiten para los archivos .mdf. En este caso, solo funciona la primera iteración que busca un grupo de archivos, y solo encuentra un solo archivo porque la conexión es solo a una sola base de datos en el entorno de alojamiento compartido.

La segunda iteración, que es una copia de la iteración que funcionó anteriormente, se ahoga inmediatamente porque la forma en que está escrita intenta acceder a la primera base de datos en el entorno compartido, que no es a la que se aplica el ID de usuario / contraseña, por lo que el servidor SQL devuelve un error de autorización en forma de error "principal del 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

En ese segundo ciclo de iteración, el código se compila bien, pero debido a que SMO no se configuró para acceder precisamente a la base de datos correcta con la sintaxis precisa, ese intento falla.

Como estoy aprendiendo SMO, pensé que otros novatos podrían apreciar saber que también hay una explicación más simple para este error: simplemente lo codificamos mal.

Alan
fuente
0

Creo que es posible que le falte una declaración "Grant Connect To" cuando creó el usuario de la base de datos.

A continuación se muestra el fragmento completo que necesitará para crear tanto un inicio de sesión contra el DBMS de SQL Server como un usuario contra la base de datos

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
fuente