Участник сервера не может получить доступ к базе данных в текущем контексте безопасности в SQL Server MS 2012

103

Я пытаюсь получить доступ к базе данных моего хостинг-сервера через SQL Server Management Studio, все до входа в систему в порядке, но когда я использую команду, use myDatabaseона дает мне эту ошибку:

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

Я поискал, и поставщики услуг хостинга перечислили это исправление проблемы.

Но это не работает для меня, вероятно, потому что это для SQL Server Management Studio 2008, однако я использую SQL Server Management Studio 2012.

Может это проблема? И если да, то кто может сказать мне его альтернативу в SSMS 2012?

Maven
источник
3
«Поставщики услуг хостинга»? Мы говорим посвященные или общие? Если это общий хостинг-сервер, я настоятельно рекомендую обратиться за помощью к вашему хостинг-провайдеру. SQL в среде общего хостинга, как известно, содержит ошибки и проблематичен. Это не имеет ничего общего с продуктом, а не с политикой, которую хостинг-провайдеры применяют к серверу (-ам). Кажется, что у каждой хостинговой компании есть свой способ использовать SQL.
Techie Joe

Ответы:

80

Проверьте, сопоставлен ли ваш пользователь с БД, в которую вы пытаетесь войти.

Скотт
источник
76
Как ты это делаешь?
Грэм
3
@Graham Либо используйте SQL Server Management Studio для проверки пользователя, либо посмотрите этот ответ: stackoverflow.com/a/9356725/804773
Grambot
5
Я бы посоветовал поискать триггеры, по этой причине я получил это сообщение, триггер выполнял какие-то действия в другой базе данных, где мой пользователь не был авторизован.
DanielV 07
1
Я ударил ошибку OP и перешел к этому ответу, я понял, что у меня только что была глупая опечатка в имени базы данных в моей строке подключения к базе данных SQL Azure. Если ваше имя базы данных правильное, вам не нужен доступ к мастеру. Если это неправильно, то (в моем случае) я думаю, что Entity Framework (6.1.3) пытается быть более умным, подключаясь к Master для получения дополнительной информации (хотя это может быть просто не связано с EF - я не уверен). Но я решил убедиться, что моя строка подключения верна. Я ожидал совсем другой ошибки из-за неправильного имени базы данных. : - /
Jaxidian
2
Чтобы добавить в комментарий @ DanielV, также проверьте хранимые процедуры для любых жестко заданных имен баз данных. Исправлено в моем случае (пришлось переделать около 20 хранимых процедур).
Demonslay335
26

У нас была такая же ошибка при развертывании отчета в SSRS в нашей среде PROD. Было обнаружено, что проблему можно даже воспроизвести с помощью оператора «использовать». Решение состояло в том, чтобы повторно синхронизировать ссылку на учетную запись GUID пользователя с рассматриваемой базой данных (т. Е. С помощью sp_change_users_login, как если бы вы делали это после восстановления базы данных). Прилагается стандартный (управляемый курсором) скрипт для повторной синхронизации всех учетных записей:

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
Сработало у меня Спасибо. Я скопировал базу данных с аутентификацией SQL-сервера на свой тестовый сервер, и она была недоступна. Теперь это
MikeH
1
Если пользователь существует в базе данных, но не может сохранить сопоставление с именем входа, удаление указанного пользователя через обозреватель объектов SSMS, а затем повторное сопоставление входа в систему сработало для меня. В противном случае я подозреваю, что придется принять предложенное выше решение.
jjt
11

Это сработало для меня:

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

Проблема может быть визуализирована с помощью:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';
азак
источник
2
Это исправило это для меня. Спасибо ! «Проблема может быть визуализирована с помощью» -> Если они возвращают другой хэш, существует проблема, и запрос выше синхронизирует их.
bezout
10

Я довольно долго боролся с этой проблемой, а затем понял, что совершаю простую ошибку, потому что забыл, на какую конкретную базу данных нацелено мое соединение. Я использовал стандартное окно подключения к SQL Server для ввода учетных данных:

Окно подключения к SQL Server

Мне пришлось проверить вкладку « Свойства подключения », чтобы убедиться, что я выбираю правильную базу данных для подключения. Я случайно оставил здесь параметр « Подключиться к базе данных» на выбор из предыдущего сеанса. Вот почему мне не удалось подключиться к базе данных, к которой я думал, что пытаюсь подключиться.

Свойства подключения

Обратите внимание, что вам нужно нажать Options >>кнопку, чтобы отобразились Свойства подключения и другие вкладки.

Фил Рингсмут
источник
7

Имена входа SQL определяются на уровне сервера и должны быть сопоставлены с пользователями в определенных базах данных.

В проводнике объектов SSMS под сервером, который вы хотите изменить, разверните Безопасность > Логины , затем дважды щелкните соответствующего пользователя, после чего откроется диалоговое окно «Свойства входа».

Выберите User Mapping , чтобы отобразить все базы данных на сервере, с теми, у которых выбрано существующее сопоставление. Отсюда вы можете выбрать дополнительные базы данных (и обязательно выбрать роли в каждой базе данных, к которым должен принадлежать пользователь), затем нажмите OK, чтобы добавить сопоставления.

введите описание изображения здесь

Эти сопоставления могут быть отключены после восстановления или аналогичной операции. В этом случае пользователь может все еще существовать в базе данных, но фактически не сопоставлен с именем входа. Если это произойдет, вы можете запустить следующее, чтобы восстановить логин:

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

Вы также можете удалить пользователя БД и воссоздать его в диалоговом окне «Свойства входа», но при этом потребуется воссоздать членство в ролях или другие параметры.

Тобиас Дж.
источник
4

В моем случае сообщение было вызвано синонимом, который случайно включил имя базы данных в «имя объекта». Когда я восстановил базу данных под новым именем, синоним все еще указывал на старое имя БД. Поскольку у пользователя не было разрешений в старой БД, появилось сообщение. Чтобы исправить это, я удалил и воссоздал синоним без уточнения имени объекта и имени базы данных:

    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

У нас была такая же ошибка, хотя пользователь был правильно сопоставлен с логином.

После попытки удалить пользователя было обнаружено, что несколько SP содержат «с выполнением от имени» этого пользователя.

Проблема была решена путем удаления этих SP, удаления пользователя, повторного создания пользователя, связанного с входом в систему, и повторного создания SP.

Возможно, он попал в это состояние из-за восстановления из резервной копии (в то время, когда соответствующий логин не существовал) или массовой синхронизации схемы (если возможно создать SP с выполнением, как даже если пользователь не существует. был связан с этим ответом .

крокусек
источник
1
Не могли бы вы пояснить, что вы подразумеваете под ИП?
Scuba Steve
1
Хранимая процедура. При создании SP (create proc xxx ...) есть необязательное предложение «с исполнением от имени <user>», которое указывает, что SP будет работать так, как если бы этот пользователь запускал его, а не текущего пользователя, вошедшего в систему.
crokusek
1

Я столкнулся с той же ошибкой при использовании объектов управления сервером (SMO) в vb.net (я уверен, что то же самое и в C #)

Комментарий Techie Joe к первоначальному посту был полезным предупреждением о том, что в виртуальном хостинге происходит много дополнительных вещей. Понадобилось немного времени, чтобы разобраться, но приведенный ниже код показывает, как нужно быть очень конкретным в способе доступа к базам данных SQL. Ошибка «принципала сервера ...», казалось, появлялась всякий раз, когда вызовы SMO не были точно конкретными в среде общего хостинга.

Этот первый раздел кода был направлен против локального сервера SQL Express и полагался на простую аутентификацию Windows. Весь код, используемый в этих примерах, основан на учебнике Роберта Канаша по SMO в этой статье веб-сайта 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

Приведенный выше код прекрасно находит файлы .mdf для каждой базы данных на локальном сервере SQLEXPRESS, потому что аутентификация обрабатывается Windows и распространяется на все базы данных.

В следующем коде есть 2 раздела, повторяющиеся для файлов .mdf. В этом случае работает только первая итерация, ищущая файловую группу, и она находит только один файл, потому что соединение осуществляется только с одной базой данных в среде общего хостинга.

Вторая итерация, которая является копией той итерации, которая работала выше, немедленно подавляется, потому что способ ее написания пытается получить доступ к 1-й базе данных в общей среде, которая не является той, к которой применяется идентификатор пользователя / пароль, поэтому SQL-сервер возвращает ошибку авторизации в виде ошибки «участник-сервер ...».

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

Во втором цикле итерации код компилируется нормально, но поскольку SMO не был настроен для доступа именно к правильной базе данных с точным синтаксисом, эта попытка не удалась.

Поскольку я только изучаю SMO, я подумал, что другим новичкам может быть интересно узнать, что есть более простое объяснение этой ошибки - мы просто неправильно ее закодировали.

Алан
источник
0

Я полагаю, что при создании пользователя базы данных вам могло не хватать инструкции «Grant Connect To».

Ниже приведен полный фрагмент кода, который вам понадобится для создания как входа в СУБД SQL Server, так и пользователя в базе данных.

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
Салим Ганджи
источник