使用 kerberos 和 spnego 从 GSS Context java 获取用户名信息

问题描述 投票:0回答:1

您好,我正在从本地 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 令牌并根据登录者获取用户信息。请帮忙

java kerberos spnego
1个回答
0
投票

据我所知,您可以获得TGT(Ticket Granting Ticket),但应用程序无法获得TGS Ticket。您可以使用 klist 命令进行验证以查看缓存中的票证。 TGS 票证取决于 TGT。

使用 kinit 命令你只能获得 TGT 而不能获得 TGS 票证。

因此,缺少的拼图似乎是应用程序所需的服务(例如 HTTP)的 SPN(服务主体名称)。

您可以使用 setspn -L 命令进行验证。

此 SPN 信息应存在于靠近应用程序客户端(应为 AD 域成员)和应用程序服务器(应为 AD 域成员)的域控制器上。

© www.soinside.com 2019 - 2024. All rights reserved.