【深度分析】關於SPN不正確致使SQL數據庫鏈接失敗

鏈接SQL Server數據庫時發生報錯「The target principal name is incorrect.  Cannot generate SSPI context」,沒法鏈接,多是因爲AD域中記錄了錯誤的SPN,致使沒法進行身份驗證而鏈接失敗。下文經過簡述Kerberos認證過程、SPN的組成,引出由SPN錯誤引起報錯的解決方法。html


Kerberos認證


1. Kerberos認證步驟


Kerberos認證須要包含KDC(Key Distribution Center)、客戶端用戶、提供服務的服務器三個組件。其中KDC是域控的一部分,執行兩個任務:認證服務(AS)、票據許可服務(TGS)ios


  • 當客戶端用戶登陸到網絡時,會向用戶所在域的AS申請一個「票據請求票據」(TGT);數據庫


  • 當客戶端要訪問網絡上某個資源時,須要出示TGT、認證碼、SPN(Server Principal Name),藉此從用戶所在域的TGS獲取session票據;編程


  • 客戶端使用這個session票據和認證碼向網絡上的服務獲取訪問令牌,接下來就能夠登陸上該服務了。windows


2. 使用Kerberos身份驗證的條件


  • 客戶端和服務器須要加域,當客戶端和服務器加入不一樣域時,兩個域須要有相互信任關係;服務器


  • 提供服務的服務器須要註冊正確的SPN。網絡


注:從Windows Server 2003開始默認使用Kerberos認證方式,當網絡上沒有註冊SPN時,就會使用NTLM認證方式,這個步驟叫作NTLM Fallback;若是網絡上有註冊SPN,但這個SPN註冊在了錯誤的帳戶下(例如不是SQL Server服務啓動帳號),則認證失敗,且不會再次嘗試NTLM認證。session



SPN(Server Principal Name)


1.SPN的組成


SPN是服務器上所運行服務的惟一標示,每一個使用Kerberos的服務都須要一個SPN,這樣客戶端才能夠辨認這個服務。SPN須要註冊在AD域的計算機帳戶或者域用戶帳戶下。app


一個SQL Server的SPN由如下元素組成:dom


服務類型:標示了服務的泛用類。對於SQL Server而言,是MSSQLSvc。


主機:有兩種形式。一個是運行SQL Server的計算機的FQDN。還有一種就是SQL Server的計算機的netbios名字,俗稱短名。


端口號/實例名:服務所監聽的計算機端口號。對於SQL Server而言,若是SQL運行在默認端口(1433)上,則端口號能夠省略。


從SQL Server 2008開始,Kerberos能夠支持TCP, Named Pipes和Shared Memory三種協議。所以對於SQL Server 2008咱們也可使用SQL Server的實例名來替代端口號(僅就命名實例而言)。


例如:

MSSQLSvc/myserver.corp.mycomany.com:1433

MSSQLSvc/myserver:1433

MSSQLSvc/myserver.corp.mycomany.com

MSSQLSvc/myserver:

MSSQLSvc/myserver.corp.mycomany.com:instancename

MSSQLSvc/myserver:instancename


注:推薦爲FQDN和netbios都註冊SPN。


2. 檢查、添加、刪除SPN


詳細的使用方法參考微軟官方文檔:

https://docs.microsoft.com/zh-cn/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc731241(v=ws.11)


查詢SPN:


在命令行輸入:


Setspn -L <Account>


其中<Account>能夠是計算機帳戶或者域用戶帳戶。

1.png

2.png

添加SPN:

在命令行輸入:


Setspn -S MSSQLSvc/server4.main.local:1433 <Account>

3.png

注:使用「Setspn -A」也能夠添加SPN,但推薦使用「Setspn -S」,由於「Setspn -S」在添加前會檢查域內是否存在相同的SPN,防止重複的SPN註冊在不一樣的帳戶下。

命令行輸入:


Setspn -X


也能夠檢查域內是否存在重複的SPN。

4.png

刪除SPN:

在命令行輸入:


Setspn -D MSSQLSvc/server4.main.local:1433 <Account>

5.png


如何爲SQL Server註冊SPN


1. 數據庫服務啓動帳戶


使用Network Service或Local System

內置帳戶Network Service和Local System表明計算機自己,SPN須要註冊在運行SQL Server的計算機帳戶下。但Network Service和Local System自己有權限爲本機註冊和刪除SPN,通常狀況不須要手動修改。(Local System權限過大,不推薦使用作服務啓動帳戶)


使用域用戶帳戶

通常域用戶沒有爲自身註冊SPN的權限,須要手動在該域用戶帳戶下注冊SPN;若是該域用戶具備本地管理員或域管理員權限,則有權限爲自身註冊或刪除SPN。


注:能夠在域控中爲特定帳戶添加註冊SPN的權限,但官方不推薦這種作法。


2. 故障處理


文字開頭提到的報錯:「Cannot generate SSPI context」

6.png

本次處理的故障是因爲更換了服務啓動帳戶,舊的SPN註冊在本地計算機帳戶下,更換後沒有自動刪除,致使域內存在不正確的SPN,沒法完成Kerberos認證。


解決方法:

刪除計算機帳戶下的SPN後,添加域用戶帳戶下的SPN。操做步驟以下:


先查詢SPN,命令行運行

Setspn -L server4

7.png

確認存在錯誤的SPN,下一步刪除,命令行執行

Setspn -D MSSQLSvc/server4.main.local:1433 server4

Setspn -D MSSQLSvc/server4.main.local server4

8.png

刪除後再爲域用戶帳戶添加SPN,命令行執行

Setspn -S MSSQLSvc/server4.main.local user-c

Setspn -S MSSQLSvc/server4.main.local:1433 user-c

9.png

添加成功後,再次查詢SPN確認,命令行執行

Setspn -L server4

Setspn -L user-c

10.png

添加成功,檢查報錯是否還存在,在SSMS執行查詢

select auth_scheme,* from sys.dm_exec_connections

11.png

鏈接成功,並且使用的是Kerberos認證。


3. 其餘常見故障


"Login Failed for user 'NT Authority\ANONYMOUS' LOGON"

客戶端可能正在使用Local System進行鏈接,並且SQL Server沒有註冊SPN,因爲Local System帳號繼承自System Context而不是一個真實的user context,因而就被當成ANONYMOUS LOGON。


解決方法:在SQL Server服務啓動帳戶下手動註冊SPN。


"Login Failed for user ' ', the user is not associated with a trusted SQL Server connection"

這種狀況是客戶端用戶沒能被SQL Server識別出:


若是客戶端程序是運行在一個本機用戶(非域用戶)或者是一個非本機管理員權限的機器賬戶(非local system)下,那麼不管SQL Server是否有註冊SPN,都會獲得這個錯誤。


解決方法:

在服務器端建立一個和客戶端用戶「同用戶名用密碼」的本機帳號,而後在SQL Server中賦予相應的登陸權限。這就是所謂pass through的方式。此時你其實是在使用SQL Server那臺計算機的同名賬戶來訪問SQL Server和相關的其餘資源。所以SQL Server機器上該賬戶的權限設置決定了客戶端的操做權限。


若是客戶端應用程序是運行在一個域用戶下的話,那麼該錯誤就說明Kerberos的驗證失敗了,這每每是因爲沒有SPN或者SPN不正確形成的。


解決方法:

註冊正確的SPN,或者刪除相應SPN放棄使用Kerberos認證。


"Could not open a connection to SQL Server[1326]"

和上面提到的故障狀況相似,但上面使用TCP鏈接,這裏咱們使用Named Pipe鏈接,解決方法同樣。


"Login failed for user '<domain>\<machinename>$' "

客戶端可能在使用Local system或者Network service運行。


解決方法:

在SQL Server的login中添加一個"domain\machinename$"帳號。其中Machinename是客戶端的計算機名。


其餘優質文章

【知識科普】普遍應用的敏捷開發方法論,極限編程與持續集成!

【Azure】混合環境下的身份驗證

【知識科普】嵌入式軟件開發是什麼?

【原型設計】如何利用Axure實現下拉子菜單?

【軟件開發】如何在DevOps實踐中,持續優化體系構建?

相關文章
相關標籤/搜索