您好,我正在从本地 PC 到 AD UAT 进行快速 POC 身份验证。 我创建了密钥表 jaas.conf。还有 krb5.conf。
Keytab 有效我可以在 Windows PC 中初始化 keytab C:\用户 ikim>kinit -k -t C:\Windows\oneapp.keytab HTTP/[电子邮件受保护] 新票证存储在缓存文件 C:\Users 中 ikim\krb5cc_rikim
但现在我的程序似乎协商令牌在 gsscontext 上无效, 我想根据我在 keytab 上指定的登录用户获取用户信息
package my.com.toyota;
import org.ietf.jgss.*;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.util.Base64;
public class Main {
public static void main(String[] args) {
// Set system properties for Kerberos configuration
System.setProperty("java.security.krb5.conf", "C:/Windows/krb5.conf"); // Path to krb5.conf
System.setProperty("java.security.auth.login.config", "C:/Windows/jaas.conf"); // Path to jaas.conf
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("sun.security.spnego.debug", "true");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); // Allow use of credentials outside the subject
System.setProperty("sun.security.krb5.disableReferrals", "true"); // Disable DNS canonicalization to avoid suffix issues
try {
// Initiate Kerberos login with LoginContext based on JAAS configuration
LoginContext loginContext = new LoginContext("com.sun.security.jgss.krb5.initiate");
loginContext.login();
System.out.println("Authenticated successfully with UAT AD!");
// Proceed with SPNEGO negotiation
String negotiateToken = performSpnegoNegotiation();
} catch (LoginException e) {
System.err.println("Login failed: " + e.getMessage());
e.printStackTrace();
} catch (GSSException e) {
throw new RuntimeException(e);
}
}
private static String performSpnegoNegotiation() throws GSSException {
// Create GSSManager instance for GSS-API
GSSManager gssManager = GSSManager.getInstance();
Oid spnegoOid = new Oid("1.3.6.1.5.5.2");
GSSName serviceName = gssManager.createName("HTTP/[email protected]", GSSName.NT_HOSTBASED_SERVICE);
// Canonicalize to mechanism-specific name
GSSName mechSpecificName = serviceName.canonicalize(spnegoOid);
// Establish the GSSContext for SPNEGO/Kerberos
GSSContext gssContext = gssManager.createContext(mechSpecificName, spnegoOid, null, GSSContext.DEFAULT_LIFETIME);
gssContext.requestMutualAuth(false);
gssContext.requestCredDeleg(true);
// Initialize the SPNEGO context
byte[] token = new byte[0];
if (!gssContext.isEstablished()) {
token = gssContext.initSecContext(token, 0, token.length);
}
// Print the SPNEGO token (Negotiate header) in Base64 format
String negotiateToken = "";
if (token != null && token.length > 0) {
negotiateToken = Base64.getEncoder().encodeToString(token);
System.out.println("SPNEGO Negotiate Token: " + negotiateToken);
} else {
System.out.println("SPNEGO negotiation completed without token.");
}
// Check if context is established and print user principal name
if (gssContext.isEstablished()) {
// Retrieve the authenticated client's principal name
System.out.println("Authenticated : " + gssContext.getSrcName().toString());
} else {
System.out.println("GSSContext not established.");
}
// Clean up the GSS context
gssContext.dispose();
return negotiateToken;
}
}
我错过了什么吗?我对这个 kerberos 也有点陌生,请帮我解决这个问题
稍后我希望我的后端验证 SPNEGO 令牌并根据登录者获取用户信息。请帮忙
据我所知,您可以获得TGT(Ticket Granting Ticket),但应用程序无法获得TGS Ticket。您可以使用 klist 命令进行验证以查看缓存中的票证。 TGS 票证取决于 TGT。
使用 kinit 命令你只能获得 TGT 而不能获得 TGS 票证。
因此,缺少的拼图似乎是应用程序所需的服务(例如 HTTP)的 SPN(服务主体名称)。
您可以使用 setspn -L 命令进行验证。
此 SPN 信息应存在于靠近应用程序客户端(应为 AD 域成员)和应用程序服务器(应为 AD 域成员)的域控制器上。