หลักเซิร์ฟเวอร์ไม่สามารถเข้าถึงฐานข้อมูลภายใต้บริบทความปลอดภัยปัจจุบันใน 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 ได้มากกว่านี้?


3
'ผู้ให้บริการโฮสติ้ง'? เรากำลังพูดถึงการทุ่มเทหรือแบ่งปัน? หากเป็นเซิร์ฟเวอร์ที่ใช้ร่วมกันฉันขอแนะนำให้ติดต่อผู้ให้บริการโฮสติ้งของคุณเพื่อขอความช่วยเหลือ SQL ในสภาพแวดล้อมการโฮสต์ที่ใช้ร่วมกันเป็นเรื่องที่มีปัญหาและมีปัญหา ไม่มีส่วนเกี่ยวข้องกับผลิตภัณฑ์ แต่นโยบายที่ผู้ให้บริการโฮสติ้งใช้กับเซิร์ฟเวอร์ บริษัท โฮสติ้งทุกแห่งมีวิธีใช้ประโยชน์จาก SQL เป็นของตัวเองหรือมากกว่านั้น
Techie Joe

คำตอบ:


81

ตรวจสอบว่าผู้ใช้ของคุณแมปกับฐานข้อมูลที่คุณพยายามเข้าสู่ระบบหรือไม่


76
คุณจะทำอย่างไร?
Graham

3
@Graham ใช้ SQL Server Management Studio เพื่อตรวจสอบผู้ใช้หรือดูคำตอบนี้: stackoverflow.com/a/9356725/804773
Grambot

5
ฉันขอแนะนำให้มองหาทริกเกอร์นั่นคือเหตุผลที่ฉันได้รับข้อความนี้มีทริกเกอร์ทำบางอย่างในฐานข้อมูลอื่นโดยที่ผู้ใช้ของฉันไม่ได้รับอนุญาต
DanielV

1
ฉันพบข้อผิดพลาดของ OP และรถถังสำหรับคำตอบนี้ฉันคิดว่าฉันพิมพ์ผิดโง่ ๆ ในชื่อฐานข้อมูลในสตริงการเชื่อมต่อของฉันที่เชื่อมต่อกับฐานข้อมูล Azure SQL หากชื่อฐานข้อมูลของคุณถูกต้องคุณไม่จำเป็นต้องเข้าถึง Master ถ้ามันผิด (ในกรณีของฉัน) ฉันคิดว่า Entity Framework (6.1.3) พยายามที่จะฉลาดเป็นพิเศษโดยเชื่อมต่อกับ Master เพื่อขอข้อมูลเพิ่มเติมบางอย่าง (แม้ว่าจะไม่เกี่ยวข้องกับ EF แต่ฉันก็ไม่แน่ใจ) แต่วิธีแก้ปัญหาของฉันคือเพื่อให้แน่ใจว่าการเชื่อมต่อของฉันถูกต้อง ฉันคาดว่าจะมีข้อผิดพลาดที่แตกต่างกันมากสำหรับชื่อฐานข้อมูลที่ไม่ถูกต้อง : - /
Jaxidian

2
หากต้องการเพิ่มความคิดเห็นของ @ DanielV ให้ตรวจสอบ Stored Procedures สำหรับชื่อฐานข้อมูลแบบฮาร์ดโค้ด แก้ไขในกรณีของฉัน (ต้องมีการเปลี่ยนแปลงขั้นตอนการจัดเก็บประมาณ 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 Object Explorer จากนั้นทำการแมปการเข้าสู่ระบบใหม่จะใช้ได้กับฉัน มิฉะนั้นฉันสงสัยว่าจะต้องดำเนินการแก้ปัญหาที่เสนอข้างต้น
jjt

12

สิ่งนี้ใช้ได้ผลสำหรับฉัน:

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

ฉันต้องตรวจสอบแท็บคุณสมบัติการเชื่อมต่อเพื่อตรวจสอบว่าฉันเลือกฐานข้อมูลที่ถูกต้องเพื่อเชื่อมต่อ ฉันเผลอปล่อยให้ตัวเลือกเชื่อมต่อกับฐานข้อมูลที่นี่ถูกตั้งค่าเป็นการเลือกจากเซสชันก่อนหน้านี้ นี่คือสาเหตุที่ฉันไม่สามารถเชื่อมต่อกับฐานข้อมูลที่ฉันคิดว่ากำลังพยายามเชื่อมต่ออยู่

คุณสมบัติการเชื่อมต่อ

โปรดทราบว่าคุณต้องคลิกOptions >>ปุ่มเพื่อให้คุณสมบัติการเชื่อมต่อและแท็บอื่น ๆ ปรากฏขึ้น


7

การเข้าสู่ระบบ SQL ถูกกำหนดที่ระดับเซิร์ฟเวอร์และต้องแมปกับผู้ใช้ในฐานข้อมูลเฉพาะ

ใน SSMS object explorer ใต้เซิร์ฟเวอร์ที่คุณต้องการแก้ไขให้ขยายSecurity > Loginsจากนั้นดับเบิลคลิกที่ผู้ใช้ที่เหมาะสมซึ่งจะเปิดกล่องโต้ตอบ "Login Properties" ขึ้นมา

เลือกการแมปผู้ใช้ซึ่งจะแสดงฐานข้อมูลทั้งหมดบนเซิร์ฟเวอร์โดยฐานข้อมูลที่เลือกไว้ จากที่นี่คุณสามารถเลือกฐานข้อมูลเพิ่มเติม (และอย่าลืมเลือกบทบาทในแต่ละฐานข้อมูลที่ผู้ใช้ควรเป็นสมาชิก) จากนั้นคลิกตกลงเพื่อเพิ่มการแมป

ป้อนคำอธิบายภาพที่นี่

การแมปเหล่านี้อาจถูกตัดการเชื่อมต่อหลังจากการกู้คืนหรือการดำเนินการที่คล้ายกัน ในกรณีนี้ผู้ใช้อาจยังคงมีอยู่ในฐานข้อมูล แต่ไม่ได้แมปกับการเข้าสู่ระบบ ในกรณีนี้คุณสามารถเรียกใช้สิ่งต่อไปนี้เพื่อกู้คืนการเข้าสู่ระบบ:

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

คุณยังสามารถลบผู้ใช้ DB และสร้างใหม่ได้จากกล่องโต้ตอบคุณสมบัติการเข้าสู่ระบบ แต่การเป็นสมาชิกบทบาทหรือการตั้งค่าอื่น ๆ จะต้องสร้างขึ้นใหม่


4

ในกรณีของฉันข้อความนั้นเกิดจากคำพ้องความหมายซึ่งรวมชื่อฐานข้อมูลไว้ใน "ชื่อวัตถุ" โดยไม่ได้ตั้งใจ เมื่อฉันเรียกคืนฐานข้อมูลภายใต้ชื่อใหม่คำพ้องความหมายยังคงชี้ไปที่ชื่อ DB เก่า เนื่องจากผู้ใช้ไม่มีสิทธิ์ในฐานข้อมูลเก่าข้อความจึงปรากฏขึ้น ในการแก้ไขฉันทิ้งคำพ้องความหมายและสร้างคำพ้องความหมายใหม่โดยไม่ได้กำหนดชื่อวัตถุด้วยชื่อฐานข้อมูล:

    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 บางตัวมี "with execute as" ผู้ใช้รายนั้น

ปัญหาได้รับการแก้ไขโดยการทิ้ง SP เหล่านั้นทิ้งผู้ใช้สร้างผู้ใช้ที่เชื่อมโยงกับการเข้าสู่ระบบและสร้าง SP ใหม่

อาจเป็นไปได้ว่ามันอยู่ในสถานะนี้จากการกู้คืนจากการสำรองข้อมูล (ในช่วงเวลาที่ไม่มีการเข้าสู่ระบบที่เกี่ยวข้อง) หรือการซิงค์สคีมาจำนวนมาก (หากเป็นไปได้ในการสร้าง SP ด้วยการดำเนินการแม้ว่าจะไม่มีผู้ใช้ก็ตามนอกจากนี้ยังมี เกี่ยวข้องกับคำตอบนี้


1
คุณสามารถอธิบายรายละเอียดเกี่ยวกับความหมายของ SPs ได้หรือไม่?
Scuba Steve

1
ขั้นตอนการเก็บ. เมื่อสร้าง SP (สร้างโปร xxx ...
crokusek

1

ฉันพบข้อผิดพลาดเดียวกันขณะใช้ Server Management Objects (SMO) ใน vb.net (ฉันแน่ใจว่าเหมือนกันใน C #)

ความคิดเห็นของ Techie Joe ในโพสต์เริ่มต้นเป็นคำเตือนที่มีประโยชน์ว่าในการแชร์โฮสติ้งจะมีสิ่งอื่น ๆ อีกมากมายเกิดขึ้น ใช้เวลาเล็กน้อยในการคิดออก แต่โค้ดด้านล่างแสดงให้เห็นว่าต้องมีความเฉพาะเจาะจงมากเพียงใดในวิธีที่พวกเขาเข้าถึงฐานข้อมูล SQL ข้อผิดพลาด 'เซิร์ฟเวอร์หลัก ... ' ดูเหมือนจะปรากฏขึ้นเมื่อใดก็ตามที่การเรียก SMO ไม่ได้เจาะจงอย่างแม่นยำในสภาพแวดล้อมการโฮสต์ที่ใช้ร่วมกัน

ส่วนแรกของโค้ดนี้ต่อต้านเซิร์ฟเวอร์ SQL Express ภายในเครื่องและอาศัยการพิสูจน์ตัวตนของ Windows อย่างง่าย รหัสทั้งหมดที่ใช้ในตัวอย่างเหล่านี้อ้างอิงจากบทช่วยสอน SMO โดย Robert Kanasz ในบทความเว็บไซต์ 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 ในสภาพแวดล้อมที่ใช้ร่วมกันซึ่งไม่ใช่รหัสที่ใช้ ID ผู้ใช้ / รหัสผ่านดังนั้น เซิร์ฟเวอร์ 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 DBMS และผู้ใช้กับฐานข้อมูล

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.