附录

附录 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 速成课程

在任何身份验证过程中,通常涉及三方。

drawio kerb cc1

首先是客户端,它有时是客户端计算机,但在大多数情况下,它是坐在计算机上并尝试访问资源的实际用户。然后是用户尝试访问的资源。在此示例中,它是一个 Web 服务器。

然后是密钥分发中心KDC。在 Windows 环境中,这将是域控制器KDC是将所有内容整合在一起的组件,因此是您环境中最重要的组件。正因为如此,它也被认为是单点故障。

最初设置Kerberos环境并将域用户主体创建到数据库中时,也会创建加密密钥。这些加密密钥基于共享密钥(即用户密码),并且实际密码从不以明文形式保存。实际上,KDC拥有自己的密钥以及域用户的其他密钥。

有趣的是,在身份验证过程中,资源KDC之间没有通信。

drawio kerb cc2

当客户端想要使用资源进行身份验证时,它首先需要与KDC通信。客户端将创建一个特殊的包,其中包含加密和未加密的部分。未加密部分包含有关用户的信息,加密部分包含协议的其他信息。客户端将使用自己的密钥加密包数据。

KDC从客户端收到此身份验证包时,它会从未加密部分检查此客户端自称的身份,并根据该信息使用它在数据库中已有的客户端解密密钥。如果此解密成功,KDC就知道此客户端就是它自称的身份。

KDC 返回给客户端的是一个名为票据授予票据的票据,该票据由 KDC 自己的私钥签名。稍后当客户端将此票据发回时,它可以尝试解密它,如果该操作成功,它就知道这是它自己最初签名并提供给客户端的票据。

drawio kerb cc3

当客户端想要获取可用于服务身份验证的票据时,TGT 会发送给KDC,然后KDC会使用服务自己的密钥签署服务票据。这是客户端服务之间建立信任的时刻。此服务票据包含只有服务本身才能解密的数据。

drawio kerb cc4

客户端使用服务进行身份验证时,它会向服务发送之前收到的服务票据,然后服务会认为我对这个人一无所知,但他给了我一个身份验证票据。服务接下来可以做的是尝试解密该票据,如果该操作成功,它就知道唯一知道我的凭据的另一方是KDC,并且因为我信任他,我也可以信任此客户端就是他自称的身份。

附录 C:设置 Kerberos 环境

本文档的范围不包括生产 Kerberos 环境的设置,但本附录提供了一些帮助,可帮助您开始为开发设置所需的组件。

设置 MIT Kerberos

第一个操作是设置一个新的域和数据库。

# 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 *

现在您可以使用kadmin和之前创建的root/admin主体。让我们创建第一个用户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并导出密钥表文件。

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的密钥表文件中。

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 的好文章和视频,但这两篇非常有用:RackspaceMicrosoft Technet

  • 已完成正常的域控制器和 Active Directory 设置。

  • 使用 DNS 域example.org和 Windows 域EXAMPLE

  • 我创建了各种域用户,如user1user2user3tomcat,并将密码设置为Password#

我最终还将所有 VM 的 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

需要使用HTTP和运行 Tomcat servlet 容器的服务器名称neo.example.org设置服务主体名称 (SPN)。这与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

第二种情况不太明显且难以追踪,因为它会导致相同的错误。如果您的 Kerberos 服务器配置错误或您的主体中只是一个简单的拼写错误导致您没有所需的加密密钥,则此特定的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被混淆了,并且简单地使用了错误的配置。您可以像我们对kinit所做的那样,通过KRB5_CONFIG环境变量告诉ldapsearch使用不同的配置。您还可以使用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目录读取策略文件。

mypolicy.json
{
  "AuthServerWhitelist" : "*.example.org",
  "AuthNegotiateDelegateWhitelist" : "*.example.org",
  "DisableAuthNegotiateCnameLookup" : true,
  "EnableAuthNegotiatePort" : true
}

Internet Explorer

完成以下步骤以确保您的 Internet Explorer 浏览器已启用 Spnego 身份验证。

  • 打开 Internet Explorer。

  • 单击工具 > Internet 选项 > 安全选项卡。

  • 本地 Intranet部分,确保您的服务器受信任,例如通过将其添加到列表中。

© . This site is unofficial and not affiliated with VMware.