Принцип роботи сервера не може отримати доступ до бази даних в поточному контексті безпеки в MS SQL Server 2012


103

Я намагаюся отримати доступ до бази даних мого сервера хостингу через студію управління SQL Server, все до входу в систему нормально, але коли я використовую команду, 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?


3
"Хостинг-провайдери"? Ми говоримо віддано чи спільно? Якщо це спільний хостинг-сервер, я настійно рекомендую звернутися за допомогою до свого постачальника хостингу. SQL у спільному хостинг-середовищі, як відомо, є помилковим та проблематичним. Це не має нічого спільного з продуктом, окрім політики, яку хостинг-провайдери застосовують до серверів. У кожної хостингової компанії є свій спосіб використовувати SQL або так здається.
Течі Джо

Відповіді:


80

Перевірте, чи ваш користувач відображений у БД, в яку ви намагаєтесь увійти.


76
як ти це робиш?
Грем

3
@Graham Або використовувати середу SQL Server Management Studio , щоб перевірити користувача або подивитися цей відповідь: stackoverflow.com/a/9356725/804773
Grambot

5
Я б запропонував шукати тригери, тому я отримав це повідомлення. У іншій базі даних, де мій користувач не був авторизований, був тригер.
DanielV

1
Я потрапив на помилку ОП і відповів на цю відповідь, я зрозумів, що у мене просто дурна помилка в Імені бази даних в моєму рядку з'єднання, що підключається до бази даних Azure SQL. Якщо ваше ім’я бази даних правильне, вам не потрібен доступ до Master. Якщо це неправильно, то (в моєму випадку) я думаю, що Entity Framework (6.1.3) намагається бути надзвичайно розумним, підключившись до Master для отримання додаткової інформації (хоча це просто не може бути пов'язано з EF - я не впевнений). Але моє рішення полягало у тому, щоб переконатися, що мій шнур зв’язку був правильним. Я очікував зовсім іншої помилки для поганого імені бази даних. : - /
Джаксидіан

2
Щоб додати коментар до @ DanielV, також перевірте "Збережені процедури" для будь-яких жорстких кодів баз даних. Виправлено це в моєму випадку (близько 20 збережених процедур довелося змінити).
Demonslay335

26

У нас була така ж помилка розгортання звіту до SSRS у нашому PROD середовищі. Було встановлено, що проблема може бути відтворена навіть із заявою "використання". Рішення полягало в тому, щоб повторно синхронізувати посилання на обліковий запис GUID користувача з відповідною базою даних (тобто, використовуючи "sp_change_users_login", як ви б відновили після відновлення db). Сценарій запасу (керований курсором) для повторної синхронізації всіх облікових записів додається:

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-сервера, і це було недоступно. Зараз це
Майк

1
Якщо Користувач існує в базі даних, але не вдається зберегти відображення входу, видалення вказаного Користувача через Провідник SSMS, а потім перезавантаження Логіну працювало для мене. В іншому випадку я підозрюю, що рішення, запропоноване вище, потрібно прийняти.
jjt

10

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

Вікно підключення до SQL Server

Мені довелося перевірити вкладку " Властивості підключення" , щоб переконатися, що я вибирав правильну базу даних для підключення. Я випадково залишив тут опцію Підключення до бази даних, встановлену для вибору з попереднього сеансу. Ось чому я не зміг підключитися до бази даних, до якої я вважав, що намагаюся підключитися.

Властивості підключення

Зауважте, що вам потрібно натиснути Options >>кнопку, щоб відобразити Властивості підключення та інші вкладки.


10

Це працювало для мене:

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

6

Логіни SQL визначаються на рівні сервера і повинні бути відображені для користувачів у конкретних базах даних.

У досліднику об'єктів SSMS під сервером, який потрібно змінити, розгорніть Безпека > Логіни , а потім двічі клацніть відповідного користувача, який відкриє діалогове вікно «Властивості входу».

Виберіть " Картування користувачів" , де будуть показані всі бази даних на сервері, з вибраними існуючими. Звідси ви можете вибрати додаткові бази даних (і не забудьте вибрати ролі у кожній базі даних, якій повинен належати користувач), а потім натисніть кнопку ОК, щоб додати відображення.

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

Ці відображення можуть бути відключені після відновлення або подібної операції. У цьому випадку користувач може все ще існувати в базі даних, але насправді не відображається на логіні. Якщо це сталося, ви можете виконати наступне, щоб відновити логін:

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

Ви також можете видалити користувача DB та відтворити його у діалоговому вікні Властивості входу, але будь-яке членство в ролі чи інші параметри потрібно буде відтворити.


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
Чи можете ви детальніше пояснити, що ви маєте на увазі під СП?
Скуба Стіва

1
Збережена процедура. Під час створення SP (create proc xxx ...) є необов'язковий пункт "з Execute as <user>", який вказує, що SP буде працювати так, як ніби цей користувач запустив його замість поточного користувача, який увійшов.
крокусек

1

Я зіткнувся з такою ж помилкою під час використання об’єктів управління сервером (SMO) на vb.net (я впевнений, що це однаково в C #)

Коментар Течі Джо до початкового повідомлення був корисним попередженням про те, що в спільному хостингу відбувається багато додаткових речей. На це знадобилося небагато часу, але наведений нижче код показує, як потрібно бути дуже конкретним у способі доступу до баз даних 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, і вона є широкою для всіх баз даних.

У наступному коді є два розділи, що повторюють файли .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

Я вважаю, що, можливо, вам не вистачає заяви "Грант-підключення до" під час створення користувача бази даних.

Нижче наведено повний фрагмент, який вам знадобиться створити як логін проти СУБД 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.