Prinsipal server tidak dapat mengakses database di bawah konteks keamanan saat ini di SQL Server MS 2012


103

Saya mencoba mengakses database server hosting saya melalui SQL Server Management Studio, semuanya sampai login baik-baik saja tetapi ketika saya menggunakan perintah use myDatabaseitu memberi saya kesalahan ini:

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

Aku mencari lebih dan penyedia layanan hosting telah terdaftar ini untuk memperbaiki masalah.

Tetapi ini tidak berfungsi untuk saya mungkin karena ini untuk SQL Server Management Studio 2008 namun saya menggunakan SQL Server Management Studio 2012.

Bisakah ini menjadi masalah? Dan jika ya daripada siapa pun dapat memberi tahu saya alternatifnya di SSMS 2012?


3
'Penyedia layanan hosting'? Apakah kita berbicara berdedikasi atau berbagi? Jika itu adalah server hosting bersama, saya sangat menyarankan untuk menghubungi penyedia hosting Anda untuk mendapatkan bantuan. SQL di lingkungan shared hosting terkenal bermasalah dan bermasalah. Ini tidak ada hubungannya dengan produk tetapi kebijakan yang diterapkan penyedia hosting ke server. Setiap perusahaan hosting memiliki cara mereka sendiri untuk memanfaatkan SQL atau begitulah tampaknya.
Techie Joe

Jawaban:


80

Periksa untuk melihat apakah pengguna Anda dipetakan ke DB yang Anda coba masuki.


76
bagaimana kamu melakukannya?
Graham

3
@Graham Gunakan SQL Server Management Studio untuk memeriksa Pengguna atau lihat jawaban ini: stackoverflow.com/a/9356725/804773
Grambot

5
Saya akan menyarankan untuk mencari pemicu, itulah alasan saya menerima pesan ini, ada pemicu yang melakukan beberapa hal di database lain di mana pengguna saya tidak diotorisasi.
DanielV

1
Saya menekan kesalahan OP dan menerima jawaban ini, saya menemukan bahwa saya baru saja salah ketik di Nama Database di string koneksi saya yang terhubung ke Azure SQL Database. Jika Nama Database Anda benar, Anda tidak memerlukan akses ke Master. Jika salah, maka (dalam kasus saya) saya pikir Entity Framework (6.1.3) mencoba menjadi lebih pintar dengan menghubungkan ke Master untuk mendapatkan beberapa informasi tambahan (meskipun itu mungkin saja tidak terkait dengan EF - saya tidak yakin). Tetapi solusi saya adalah memastikan string koneksi saya benar. Saya mengharapkan kesalahan yang sangat berbeda untuk nama database yang buruk. : - /
Jaxidian

2
Untuk menambahkan ke komentar @ DanielV, periksa juga Prosedur Tersimpan untuk nama database hardcode. Memperbaiki itu dalam kasus saya (sekitar 20 prosedur tersimpan harus diubah).
Demonslay335

26

Kami mengalami kesalahan yang sama saat menerapkan laporan ke SSRS di lingkungan PROD kami. Ditemukan bahwa masalah bahkan dapat direproduksi dengan pernyataan "gunakan". Solusinya adalah menyinkronkan ulang referensi akun GUID pengguna dengan database yang dimaksud (yaitu, menggunakan "sp_change_users_login" seperti yang Anda lakukan setelah memulihkan db). Sebuah skrip saham (digerakkan oleh kursor) untuk menyinkronkan ulang semua akun dilampirkan:

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
Bekerja untuk saya Terima kasih. Saya telah menyalin database dengan otentikasi server SQL ke server pengujian saya dan itu tidak dapat diakses. Sekarang
MikeH

1
Jika Pengguna ada di database tetapi gagal mempertahankan pemetaan ke Login, menghapus Pengguna tersebut melalui SSMS Object Explorer kemudian memetakan kembali Login berfungsi untuk saya. Jika tidak, saya curiga solusi yang diusulkan di atas perlu diambil.
jjt

10

Saya menghabiskan cukup banyak waktu untuk bergulat dengan masalah ini dan kemudian saya menyadari bahwa saya membuat kesalahan sederhana dengan fakta bahwa saya lupa database mana yang saya targetkan untuk koneksi saya. Saya menggunakan jendela koneksi SQL Server standar untuk memasukkan kredensial:

Jendela Koneksi SQL Server

Saya harus memeriksa tab Connection Properties untuk memverifikasi bahwa saya memilih database yang benar untuk disambungkan. Saya secara tidak sengaja membiarkan opsi Hubungkan ke database di sini diatur ke pilihan dari sesi sebelumnya. Inilah mengapa saya tidak dapat terhubung ke database yang saya pikir saya coba sambungkan.

Properti Koneksi

Perhatikan bahwa Anda perlu mengklik Options >>tombol agar Connection Properties dan tab lain muncul.


10

Ini berhasil untuk saya:

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

Masalahnya dapat divisualisasikan dengan:

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

2
Ini memperbaikinya untuk saya. Terima kasih! "Masalah dapat divisualisasikan dengan" -> Jika mereka mengembalikan hash yang berbeda, ada masalah dan kueri di atas akan menyinkronkannya.
sebelum

7

SQL Login didefinisikan di tingkat server, dan harus dipetakan ke Pengguna dalam database tertentu.

Di penjelajah objek SSMS, di bawah server yang ingin Anda ubah, luaskan Keamanan > Masuk , lalu klik dua kali pengguna yang sesuai yang akan memunculkan dialog "Properti Masuk".

Pilih Pemetaan Pengguna , yang akan menampilkan semua database di server, dengan yang telah dipilih pemetaannya. Dari sini Anda dapat memilih database tambahan (dan pastikan untuk memilih peran mana di setiap database yang harus dimiliki pengguna), lalu klik OK untuk menambahkan pemetaan.

masukkan deskripsi gambar di sini

Pemetaan ini dapat terputus setelah pemulihan atau operasi serupa. Dalam kasus ini, pengguna mungkin masih ada di database tetapi sebenarnya tidak dipetakan ke login. Jika itu terjadi, Anda dapat menjalankan perintah berikut untuk memulihkan login:

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

Anda juga dapat menghapus pengguna DB dan membuatnya kembali dari dialog Properti Login, tetapi semua peran keanggotaan atau pengaturan lain perlu dibuat ulang.


4

Dalam kasus saya, pesan tersebut disebabkan oleh sinonim yang secara tidak sengaja memasukkan nama database di "nama objek". Ketika saya memulihkan database dengan nama baru, sinonimnya masih menunjuk ke nama DB lama. Karena pengguna tidak memiliki izin di DB lama, pesan tersebut muncul. Untuk memperbaikinya, saya menjatuhkan dan membuat ulang sinonim tanpa mengkualifikasi nama objek dengan nama 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

Kami mengalami kesalahan yang sama meskipun pengguna telah dipetakan dengan benar ke proses masuk.

Setelah mencoba untuk menghapus pengguna, ditemukan bahwa beberapa SP berisi "dengan mengeksekusi sebagai" pengguna itu.

Masalah ini diselesaikan dengan menghapus SP tersebut, menjatuhkan pengguna, membuat ulang pengguna yang ditautkan untuk masuk, dan membuat ulang SP.

Mungkin itu dalam keadaan ini dari memulihkan dari cadangan (selama waktu ketika login terkait tidak ada) atau sinkronisasi skema massal (jika memungkinkan untuk membuat SP dengan mengeksekusi seolah-olah pengguna tidak ada. Bisa juga memiliki terkait dengan jawaban ini .


1
Bisakah Anda menjelaskan apa yang Anda maksud dengan SPs?
Scuba Steve

1
Prosedur Tersimpan. Saat membuat SP (buat proc xxx ...), ada klausa opsional "dengan mengeksekusi sebagai <user>" yang menentukan bahwa SP akan berjalan seolah-olah pengguna yang menjalankannya, bukan pengguna yang saat ini masuk.
crokusek

1

Saya mengalami kesalahan yang sama saat menggunakan Server Management Objects (SMO) di vb.net (Saya yakin itu sama di C #)

Komentar Techie Joe pada posting awal adalah peringatan yang berguna bahwa dalam shared hosting banyak hal tambahan yang terjadi. Butuh sedikit waktu untuk mengetahuinya, tetapi kode di bawah ini menunjukkan bagaimana seseorang harus sangat spesifik dalam cara mereka mengakses database SQL. Kesalahan 'server principal ...' tampaknya muncul setiap kali panggilan SMO tidak spesifik secara spesifik di lingkungan shared hosting.

Bagian pertama kode ini melawan server SQL Express lokal dan mengandalkan Autentikasi Windows sederhana. Semua kode yang digunakan dalam sampel ini didasarkan pada tutorial SMO oleh Robert Kanasz dalam artikel situs web Proyek Kode ini :

  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

Kode di atas menemukan file .mdf untuk setiap database di server SQLEXPRESS lokal dengan baik karena otentikasi ditangani oleh Windows dan itu luas di semua database.

Dalam kode berikut, ada 2 bagian yang melakukan iterasi untuk file .mdf. Dalam kasus ini, hanya iterasi pertama yang mencari filegroup yang berfungsi, dan hanya menemukan satu file karena koneksi hanya ke satu database di lingkungan hosting bersama.

Iterasi kedua, yang merupakan salinan dari iterasi yang bekerja di atas, langsung tersedak karena cara penulisannya mencoba mengakses database pertama di lingkungan bersama, yang bukan database yang diterapkan oleh User ID / Password, jadi server SQL mengembalikan kesalahan otorisasi dalam bentuk kesalahan '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

Dalam perulangan iterasi kedua, kode dikompilasi dengan baik, tetapi karena SMO tidak diatur untuk mengakses database yang benar dengan sintaks yang tepat, upaya itu gagal.

Karena saya baru belajar SMO, saya pikir pemula lain mungkin menghargai mengetahui ada juga penjelasan yang lebih sederhana untuk kesalahan ini - kami hanya salah mengkodekannya.


0

Saya yakin Anda mungkin kehilangan pernyataan "Grant Connect To" saat Anda membuat pengguna database.

Di bawah ini adalah cuplikan lengkap yang Anda perlukan untuk membuat login pada SQL Server DBMS serta pengguna terhadap 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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.