gpt4 book ai didi

java - 从授权 header 中的 Kerberos 票证中读取用户名

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:56:03 24 4
gpt4 key购买 nike

我想从授权 HTTP header 中的 Kerberos 票证中读取用户名。我正在使用 Java。

我花了好几天的时间阅读有关该主题的大量网站,试图实现这一目标,但未能做到这一点。 Kerberos 对我来说是新的/陌生的。

这是我取得的成就:

  • 当用户首次访问网站时 - 没有 Authorization header ,服务器会使用 401 + header 进行响应:WWW-Authenticate=Negotiate。
  • 客户端会发生各种神奇的事情。
  • 用户返回一个 HTTP 请求,其中包含 Authorization header ,其值类似于:“Negotiate YHcGB ...==”
  • 将 base64 编码的票解码为字节数组。

从这里开始,这是一段穿越未知的可怕旅程。据我所知,接下来的步骤应该是:

  • 以用户身份登录到 AD/Kerberos/服务器。
  • 解码票证。

这是我的:

登录配置文件

 ServicePrincipalLoginContext
{
com.sun.security.auth.module.Krb5LoginModule
required
principal="HTTP/some.server.com@MY.DOMAIN.COM"
doNotPrompt=true
useTicketCache=true
password=mYpasSword
debug=true;
};

Java类.java

String encodedTicket = authorization.substring("Negotiate ".length());
byte[] ticket = Base64.decode(encodedTicket);

LoginContext lc = new LoginContext("ServicePrincipalLoginContext");
lc.login();
Subject serviceSubject = lc.getSubject();
Subject.doAs(serviceSubject, new ServiceTicketDecoder(ticket));

ServiceTicketDecoder.java

public String run() throws Exception {
Oid kerberos5Oid = new Oid("1.2.840.113554.1.2.2");

GSSManager gssManager = GSSManager.getInstance();

String service = "krbtgt/MY.DOMAIN.COM@MY.DOMAIN.COM";
GSSName serviceName = gssManager.createName(service, GSSName.NT_USER_NAME);

GSSCredential serviceCredentials = gssManager.createCredential(serviceName, GSSCredential.INDEFINITE_LIFETIME, kerberos5Oid, GSSCredential.ACCEPT_ONLY);

GSSContext gssContext = gssManager.createContext(serviceCredentials);
gssContext.acceptSecContext(this.serviceTicket, 0, this.serviceTicket.length);

GSSName srcName = gssContext.getSrcName();
return srcName.toString;
}

JavaClass.java 中的登录正常,所以我假设 login.conf 正常。在 ServiceTicketDecoder.java 中的“GSSCredential serviceCredentials = gssManager.createCredential(...”上,抛出以下异常:

java.security.PrivilegedActionException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos Key)

我不确定这是否是正确的方法。我也不知道“字符串服务”的值(value)应该是多少或如何获取该信息。你能帮帮我吗?


编辑:登录配置文件

 ServicePrincipalLoginContext
{
com.sun.security.auth.module.Krb5LoginModule
required
principal="HTTP/some.server.com@MY.DOMAIN.COM"
doNotPrompt=true
useTicketCache=true
keyTab="C:/server-http.keytab"
debug=true;
};

我收到了一个 key 表文件。显然 HTTP/some.server.com 用户的帐户已经是服务主体帐户。我现在在 lc.login() 的 JavaClass.java 上遇到问题:

javax.security.auth.login.LoginException: KDC has no support for encryption type (14)
Caused by: KrbException: KDC has no support for encryption type (14)
Caused by: KrbException: Identifier doesn't match expected value (906)

keytab 文件是用 des-cbc-md5 加密的,我在 krb.conf 文件中定义了以下内容:

[libdefaults]
default_realm = MY.DOMAIN.COM
default_tkt_enctypes = des-cbc-md5
default_tgs_enctypes = des-cbc-md5

如果我将默认的 enctypes 更改为例如aes128-cts,我得到以下异常:

javax.security.auth.login.LoginException: Do not have keys of types listed in default_tkt_enctypes available; only have keys of following type: DES CBC mode with MD5

我不明白哪里出了问题...

最佳答案

Kerberos 是一个可信的第三方安全系统:您从客户端收到的安全 token 只能由您解密,而无需联系任何 Kerberos 基础架构服务器(例如 KDC)。你走在正确的轨道上;但是,您似乎缺少指导您进一步研究的 Kerberos 背景知识。

实现这一点的方法是,在服务器上您需要一个包含服务器 key 的keytab 文件。 Kerberos 服务器(我假设是 Microsoft Windows Server)必须有一个为您的服务创建的服务主体帐户。管理员可以为您提供为此帐户生成的 key 表文件,其中将包含 key 。

然后你需要配置服务器来找到这个keytab文件;它用于涉及 LoginContext.login 的服务器端步骤。接受安全上下文的代码必须在服务器端凭证生效的 doPrivileged 代码段内执行。

关于java - 从授权 header 中的 Kerberos 票证中读取用户名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14354414/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com