附錄
附錄 A:本文檔中使用的材料
範例中使用的虛擬 UserDetailsService,因為我們沒有真實的使用者來源。
public class DummyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
return new User(username, "notUsed", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_USER"));
}
}
附錄 B:Kerberos 快速入門
在任何身份驗證過程中,通常都涉及三個參與方。
首先是用戶端
,有時是用戶端電腦,但在大多數情況下,它是坐在電腦前並嘗試存取資源的實際使用者。然後是用戶嘗試存取的資源
。在本例中,它是一台網路伺服器。
然後是金鑰發放中心
或 KDC
。在 Windows 環境中,這將是網域控制器
。KDC
是真正將所有事物整合在一起的角色,因此也是您環境中最關鍵的組件。因此,它也被視為單點故障。
最初,當 Kerberos
環境設定完成並將網域使用者主體建立到資料庫中時,也會建立加密金鑰。這些加密金鑰基於共享密碼(即使用者密碼),而實際密碼永遠不會以明文形式保存。實際上,KDC
擁有自己的金鑰和其他網域使用者的金鑰。
有趣的是,在身份驗證過程中,資源
和 KDC
之間沒有任何通訊。
當用戶端想要向 資源
驗證自身身份時,它首先需要與 KDC
通訊。用戶端
將製作一個特殊封包,其中包含加密和未加密的部分。未加密的部分包含例如有關使用者的資訊,而加密部分包含協定一部分的其他資訊。用戶端
將使用自己的金鑰加密封包資料。
當 KDC
從用戶端收到此身份驗證封包時,它會從未加密的部分檢查此 用戶端
聲稱是誰,並根據該資訊,它會使用已在其資料庫中擁有的 用戶端
解密金鑰。如果此解密成功,KDC
知道此 用戶端
就是它聲稱的身份。
KDC 返回給用戶端的是一個稱為 票證授予票證
的票證,該票證由 KDC 自己的私鑰簽署。稍後,當 用戶端
發回此票證時,它可以嘗試解密它,如果該操作成功,它就知道這是一個票證,是它自己最初簽署並給予 用戶端
的。
當用戶端想要取得可用於向服務驗證身份的票證時,TGT
會被發送到 KDC
,然後 KDC
使用服務自己的金鑰簽署服務票證。這是建立 用戶端
和 服務
之間信任的時刻。此服務票證包含只有 服務
本身才能解密的資料。
當 用戶端
向服務進行身份驗證時,它會將先前收到的服務票證發送到服務,然後服務會認為我不了解這個人,但他給了我一張身份驗證票證。服務
接下來可以做的是嘗試解密該票證,如果該操作成功,它就知道唯一知道我的憑證的另一方是 KDC
,並且因為我信任他,所以我也可以信任這個用戶端是他聲稱的身份。
附錄 C:設定 Kerberos 環境
Kerberos 環境的生產設定超出本文檔的範圍,但此附錄提供了一些幫助,讓您開始設定開發所需的組件。
設定 MIT Kerberos
第一個動作是設定新的 realm 和資料庫。
# kdb5_util create -s -r EXAMPLE.ORG
Loading random data
Initializing database '/var/lib/krb5kdc/principal' for realm 'EXAMPLE.ORG',
master key name 'K/[email protected]'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key:
Re-enter KDC database master key to verify:
kadmin
命令可用於管理 Kerberos 環境,但您還不能使用它,因為資料庫中沒有管理員使用者。
root@neo:/etc/krb5kdc# kadmin
Authenticating as principal root/[email protected] with password.
kadmin: Client not found in Kerberos database while initializing
kadmin interface
讓我們使用 kadmin.local
命令來建立一個。
root@neo:/etc/krb5kdc# kadmin.local
Authenticating as principal root/[email protected] with password.
kadmin.local: listprincs
K/[email protected]
kadmin/[email protected]
kadmin/[email protected]
kadmin/[email protected]
krbtgt/[email protected]
kadmin.local: addprinc root/[email protected]
WARNING: no policy specified for root/[email protected]; defaulting to
no policy
Enter password for principal "root/[email protected]":
Re-enter password for principal "root/[email protected]":
Principal "root/[email protected]" created.
然後透過修改 kadm5.acl
檔案並重新啟動 Kerberos 服務來啟用管理員。
# cat /etc/krb5kdc/kadm5.acl
# This file Is the access control list for krb5 administration.
*/admin *
現在您可以使用先前建立的 root/admin
主體來使用 kadmin
。讓我們建立我們的第一個使用者 user1
。
kadmin: addprinc user1
WARNING: no policy specified for [email protected]; defaulting to no
policy
Enter password for principal "[email protected]":
Re-enter password for principal "[email protected]":
Principal "[email protected]" created.
讓我們建立我們的第二個使用者 user2
並匯出 keytab 檔案。
kadmin: addprinc user2
WARNING: no policy specified for [email protected]; defaulting to no
policy
Enter password for principal "[email protected]":
Re-enter password for principal "[email protected]":
Principal "[email protected]" created.
kadmin: ktadd -k /tmp/user2.keytab [email protected]
Entry for principal [email protected] with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/tmp/user2.keytab.
Entry for principal [email protected] with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/tmp/user2.keytab.
Entry for principal [email protected] with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/tmp/user2.keytab.
Entry for principal [email protected] with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:/tmp/user2.keytab.
讓我們為 tomcat 建立一個服務票證,並將憑證匯出到名為 tomcat.keytab
的 keytab 檔案。
kadmin: addprinc -randkey HTTP/[email protected]
WARNING: no policy specified for HTTP/[email protected];
defaulting to no policy
Principal "HTTP/[email protected]" created.
kadmin: ktadd -k /tmp/tomcat.keytab HTTP/[email protected]
Entry for principal HTTP/[email protected] with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/tmp/tomcat2.keytab.
Entry for principal HTTP/[email protected] with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/tmp/tomcat2.keytab.
Entry for principal HTTP/[email protected] with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/tmp/tomcat2.keytab.
Entry for principal HTTP/[email protected] with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:/tmp/tomcat2.keytab.
設定 Windows 網域控制器
這是使用 Windows Server 2012 R2
測試的
網路上有很多關於如何設定 Windows AD 的好文章和影片,但這兩篇相當有用 Rackspace 和 Microsoft Technet。 |
-
已完成正常的網域控制器和 Active Directory 設定。
-
使用的 dns 網域
example.org
和 Windows 網域EXAMPLE
。 -
我建立了各種網域使用者,例如
user1
、user2
、user3
、tomcat
,並將密碼設定為Password#
。
我最終還將我所有虛擬機器的 IP 新增到 AD 的 dns 伺服器,以避免造成任何問題。
Name: WIN-EKBO0EQ7TS7.example.org
Address: 172.16.101.135
Name: win8vm.example.org
Address: 172.16.101.136
Name: neo.example.org
Address: 172.16.101.1
服務主體名稱 (SPN) 需要使用 HTTP
和伺服器名稱 neo.example.org
進行設定,其中執行 tomcat servlet 容器。這與 tomcat
網域使用者一起使用,其 keytab
然後用作服務憑證。
PS C:\> setspn -A HTTP/neo.example.org tomcat
我匯出了 keytab 檔案,該檔案被複製到執行 tomcat 的 Linux 伺服器。
PS C:\> ktpass /out c:\tomcat.keytab /mapuser [email protected] /princ HTTP/[email protected] /pass Password# /ptype KRB5_NT_PRINCIPAL /crypto All
Targeting domain controller: WIN-EKBO0EQ7TS7.example.org
Using legacy password setting method
Successfully mapped HTTP/neo.example.org to tomcat.
附錄 D:疑難排解
本附錄提供關於疑難排解錯誤和問題的通用資訊。
如果您認為環境和設定已正確設定,請仔細檢查並請其他人檢查可能的明顯錯誤或錯字。Kerberos 設定通常非常脆弱,並且並不總是很容易偵錯問題所在。 |
GSSException: Failure unspecified at GSS-API level (Mechanism level:
Invalid argument (400) - Cannot find key of appropriate type to
decrypt AP REP - RC4 with HMAC)
如果您看到指示缺少金鑰類型的錯誤,則會在兩種不同的用例中發生這種情況。首先,您的 JVM 可能不支援適當的加密類型,或者它在您的 krb5.conf
檔案中被停用。
default_tkt_enctypes = rc4-hmac
default_tgs_enctypes = rc4-hmac
第二種情況不太明顯且難以追蹤,因為它會導致相同的錯誤。如果您根本沒有所需的加密金鑰,也會拋出此特定的 GSSException
,這可能是由於您的 Kerberos 伺服器中的錯誤設定或主體中的簡單錯字造成的。
在大多數系統中,所有命令和程式庫都會從預設位置或特殊位置(例如 JDK)搜尋 Kerberos 設定。很容易混淆,尤其是在從 Unix 系統(可能已經具有與 MIT Kerberos 配合使用的預設設定)轉向 Windows 網域時。
這是一個具體的範例,說明 ldapsearch
嘗試使用 Kerberos 身份驗證查詢 Windows AD 時會發生什麼情況。
$ ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org -b "dc=example,dc=org"
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error:
Unspecified GSS failure. Minor code may provide more information
(No Kerberos credentials available)
這看起來不太好,並且簡單地表明我沒有有效的 Kerberos 票證,如下所示。
$ klist
klist: Credentials cache file '/tmp/krb5cc_1000' not found
我們已經有一個從 Windows AD 匯出的 keytab 檔案,用於在 Linux 上執行的 tomcat。讓我們嘗試使用它向 Windows AD 進行身份驗證。
您可以擁有一個專用的設定檔,該設定檔通常可以透過系統屬性與原生 Linux 命令和 JVM 一起使用。
$ cat krb5.ini
[libdefaults]
default_realm = EXAMPLE.ORG
default_keytab_name = /tmp/tomcat.keytab
forwardable=true
[realms]
EXAMPLE.ORG = {
kdc = WIN-EKBO0EQ7TS7.example.org:88
}
[domain_realm]
example.org=EXAMPLE.ORG
.example.org=EXAMPLE.ORG
讓我們使用該設定檔和 keytab 來取得初始憑證。
$ env KRB5_CONFIG=/path/to/krb5.ini kinit -kt tomcat.keytab HTTP/[email protected]
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: HTTP/[email protected]
Valid starting Expires Service principal
26/03/15 09:04:37 26/03/15 19:04:37 krbtgt/[email protected]
renew until 27/03/15 09:04:37
讓我們看看如果我們現在嘗試對 Windows AD 進行簡單查詢會發生什麼情況。
$ ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org -b "dc=example,dc=org"
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error:
Unspecified GSS failure. Minor code may provide more information
(KDC returned error string: PROCESS_TGS)
這可能僅僅是因為 ldapsearch
感到困惑並且只是使用了錯誤的設定。您可以告訴 ldapsearch
使用不同的設定,透過 KRB5_CONFIG
環境變數,就像我們對 kinit
所做的那樣。您也可以使用 KRB5_TRACE=/dev/stderr
來取得有關原生程式庫正在執行的操作的更詳細輸出。
$ env KRB5_CONFIG=/path/to/krb5.ini ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org -b "dc=example,dc=org"
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: HTTP/[email protected]
Valid starting Expires Service principal
26/03/15 09:11:03 26/03/15 19:11:03 krbtgt/[email protected]
renew until 27/03/15 09:11:03
26/03/15 09:11:44 26/03/15 19:11:03
ldap/[email protected]
renew until 27/03/15 09:11:03
在上面您可以看到如果查詢透過查看 Kerberos 票證而成功會發生什麼情況。現在您可以嘗試進一步的查詢命令,例如,如果您使用 KerberosLdapContextSource
。
$ ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org \
-b "dc=example,dc=org" \
"(| ([email protected])
([email protected]))" \
dn
...
# test user, example.org
dn: CN=test user,DC=example,DC=org
附錄 E:設定瀏覽器以進行 Spnego 協商
Firefox
完成以下步驟以確保您的 Firefox 瀏覽器已啟用以執行 Spnego 身份驗證。
-
開啟 Firefox。
-
在網址欄位中,輸入 about:config。
-
在篩選器/搜尋中,輸入 negotiate。
-
參數 network.negotiate-auth.trusted-uris 可能設定為預設值 https://,這對您不起作用。一般來說,如果需要 Kerberos 委派,則必須將此參數替換為伺服器位址。
-
建議對所有通訊使用
https
。
Chrome
使用 Google Chrome,您通常需要設定命令列參數順序,以將伺服器列入白名單,Chrome 將與之協商。
-
在 Windows 機器(用戶端)上:Chrome 與 Internet Explorer 共享設定,因此如果所有變更都已應用於 IE(如 E.3 中所述),則無需透過命令列參數傳遞任何內容。
-
在 Linux/Mac OS 機器(用戶端)上:只有在需要 Kerberos 委派時才應使用命令列參數
--auth-negotiate-delegate-whitelist
(否則請勿設定此參數)。 -
建議對所有通訊使用
https
。
--auth-server-whitelist="*.example.com"
--auth-negotiate-delegate-whitelist="*.example.com"
您可以透過在 Chrome 的網址列中輸入 chrome://policy/ 來查看啟用了哪些策略。
使用 Linux Chrome 也會從 /etc/opt/chrome/policies/managed
目錄讀取策略檔案。
{
"AuthServerWhitelist" : "*.example.org",
"AuthNegotiateDelegateWhitelist" : "*.example.org",
"DisableAuthNegotiateCnameLookup" : true,
"EnableAuthNegotiatePort" : true
}