java连接AD(Microsoft Active Directory)模拟用户登录认证

news2024/11/19 4:39:51

在这里插入图片描述

文章目录

  • 一、背景
  • 二、页面效果
  • 三、代码
    • LdapLoginRequest请求实体类
    • Response返回结果
    • Msg
    • ADTest测试类
      • 补充说明
      • 代码
  • 四、认证结果
    • 认证成功
    • 认证失败
  • 本人其他相关文章链接

一、背景

亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍报错以及配置用处,根本不懂照抄那些配置是干啥的,稀里糊涂的按照博客搭完也跑不起来,因此记录这个。

项目背景:公司项目当前采用http协议+shiro+mysql的登录认证方式,而现在想支持ldap协议认证登录然后能够访问自己公司的项目网站。

举例说明:假设我们公司有自己的门户网站,现在我们收购了一家公司,他们数据库采用ldap存储用户数据,那么为了他们账户能登陆我们公司项目所以需要集成,而不是再把他们的账户重新在mysql再创建一遍,万一人家有1W个账户呢,不累死了且也不现实啊。

需要安装AD+kerberos,且ldap和kerberos安装在同一台服务器上,当前版本如下:

  • windows server 2016
  • 服务器IP:10.110.25.48

我公司电脑室windows10的,我是VietualBox安装的windows server 2016,类似安装个虚拟机,然后去安装AD。

二、页面效果

在这里插入图片描述

前提条件
需要先搭建LDAP环境(AD或者Openldap)情况下,再进行如下操作比如点击“测试连接”按钮查看是否能通。

  • Upload ldap public Key按钮:上传ldap的公钥,通常用于加密通信或者验证数字签名,特别是在安全和认证领域中使用较多。
  • Upload kerberos keytab按钮:上传kerberos的keytab文件,通常用于存储主体(Principal)的加密密钥的文件,可实现用户无密码登录或者安全认证等操作。(该文件可上传可不上传,区别就在认证方式不一样而已)
  • Ldap IP urls:配置LDAP服务器的IP。
  • Ldap account name:配置用于测试连接的账户名。
  • Ldap account password:配置用于测试连接的账户密码。
  • Domain name:搭建AD与服务器的时候,配置设置的根域名。
  • 测试按钮:用于测试连接登录认证是否成功。
  • 应用按钮:用于保存数据库入库。

三、代码

LdapLoginRequest请求实体类

package com.example.ldaptest2.entity;

public class LdapLoginRequest {
    private String username;

    private String password;

    private String principal;

    /**
     * kerberos keytab文件的绝对路径
     */
    private String keytabFilePath;

    /**
     * ldap服务器标识,只能为1或2
     */
    private String ldapFlag;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPrincipal() {
        return principal;
    }

    public void setPrincipal(String principal) {
        this.principal = principal;
    }

    public String getKeytabFilePath() {
        return keytabFilePath;
    }

    public void setKeytabFilePath(String keytabFilePath) {
        this.keytabFilePath = keytabFilePath;
    }

    public String getLdapFlag() {
        return ldapFlag;
    }

    public void setLdapFlag(String ldapFlag) {
        this.ldapFlag = ldapFlag;
    }

    @Override
    public String toString() {
        return "LdapLoginRequest{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", principal='" + principal + '\'' +
                ", keytabFilePath='" + keytabFilePath + '\'' +
                ", ldapFlag='" + ldapFlag + '\'' +
                '}';
    }
}

Response返回结果

package com.example.ldaptest2;

import com.example.ldaptest2.entity.LdapLoginRequest;
import com.example.ldaptest2.entity.Response;
import com.sun.security.auth.module.Krb5LoginModule;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.security.krb5.Config;
import sun.security.krb5.KrbException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * AD域登录认证
 */
public class ADTest {
    private static final Logger log = LoggerFactory.getLogger(ADTest.class);
    public static final String LDAP_SERVER1_CONFIG_PATH = "C:\\Users\\211145187\\Desktop\\fsdownload";
    public static final String KERBEROS_KEYTAB_CONFIG_PATH = "C:\\Users\\211145187\\Desktop\\fsdownload\\ldap.keytab";
    public static final String KRB5_CONF_FILE_NAME = "krb5.conf";
    public static final String KEYSTORE_FILE_NAME = "ldap_keystore.jks";
    //kerberos的认证命令密码:明文是ldap@1993
    public static final String KEYSTORE_PASSWORD = "bGRhcEAxOTkz";
    public static final String KEYSTORE_TYPE = "JKS";

    public static void main(String[] args) {
        LdapLoginRequest request = new LdapLoginRequest();
        request.setUsername("testuser26");
        request.setPassword("Bingo@1993");
        request.setPrincipal("testuser26@TESTLDAP.CAT.COM");
        request.setKeytabFilePath(KERBEROS_KEYTAB_CONFIG_PATH);

        File keystoreFile = new File(LDAP_SERVER1_CONFIG_PATH + File.separator + KEYSTORE_FILE_NAME);
        if (keystoreFile.exists()) {
            try {
                setCertificate(LDAP_SERVER1_CONFIG_PATH + File.separator + KEYSTORE_FILE_NAME);
            } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException |
                    KeyManagementException e) {
                log.error("SSL证书加载异常");
                return;
            }
        }
        Response response = null;
        if (StringUtils.isNotBlank(request.getKeytabFilePath())) {
            File keytabFile = new File(request.getKeytabFilePath());
            if (keytabFile.exists()) {
                response = loginWithKeytab(request, LDAP_SERVER1_CONFIG_PATH);
                log.info("response from loginWithKeytab:{}", response);
            } else {
                log.warn("keytab file does not exit");
            }
        }
        if (response != null && response.getCode() == 200) {
            return;
        } else {
            response = loginWithPassword(request, LDAP_SERVER1_CONFIG_PATH);
            log.info("response from loginWithPassword:{}", response);
            return;
        }
    }


    private static class KerberosCallbackHandler implements javax.security.auth.callback.CallbackHandler {
        private final String username;
        private final String password;

        public KerberosCallbackHandler(String username, String password) {
            this.username = username;
            this.password = password;
        }

        @Override
        public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
            for (Callback callback : callbacks) {
                if (callback instanceof NameCallback) {
                    ((NameCallback) callback).setName(username);
                } else if (callback instanceof PasswordCallback) {
                    ((PasswordCallback) callback).setPassword(password.toCharArray());
                } else {
                    throw new UnsupportedCallbackException(callback);
                }
            }
        }
    }

    private void refreshConfig() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<?> configClass = Config.class;
        Field instanceField = configClass.getDeclaredField("instance");
        instanceField.setAccessible(true);
        instanceField.set(null, null);
        Method refreshMethod = configClass.getDeclaredMethod("refresh");
        refreshMethod.setAccessible(true);
        refreshMethod.invoke(null);
    }

    private static Response loginWithPassword(LdapLoginRequest request, String configPath) {
        try {
            sun.security.krb5.Config.refresh();
//            refreshConfig();
        } catch (KrbException e) {
            log.error("refresh config error", e);
        }
        System.setProperty("java.security.krb5.conf", configPath + File.separator + KRB5_CONF_FILE_NAME);
        System.setProperty("sun.security.krb5.debug", "true");

        LoginContext loginContext = null;
        try {
            loginContext = new LoginContext("com.sun.security.jgss.krb5.initiate", null, new KerberosCallbackHandler(request.getUsername(), request.getPassword()),
                    new Configuration() {
                        @Override
                        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                            Map<String, String> options = new HashMap<>();
                            options.put("useKeyTab", "false");
                            options.put("useTicketCache", "false");
                            options.put("storeKey", "true");
                            options.put("refreshKrb5Config", "true");
                            return new AppConfigurationEntry[]{
                                    new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
                                            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options)
                            };
                        }
                    });
            loginContext.login();
            Subject subject = loginContext.getSubject();
            return checkTicket(subject);
        } catch (LoginException e) {
            log.error("login error: ", e);
            return handleException(e);
        } finally {
            try {
                if (loginContext != null) {
                    loginContext.logout();
                }
                log.info("loginWithPassword login success!");
            } catch (LoginException e) {
                log.error("logout error: ", e);
            }
        }
    }

    private static Response loginWithKeytab(LdapLoginRequest request, String configPath) {
        try {
            sun.security.krb5.Config.refresh();
//            refreshConfig();
        } catch (KrbException e) {
            log.error("refresh config error", e);
        }
        if (StringUtils.isBlank(request.getKeytabFilePath())) {
            return Response.error("非法参数异常");
        }
        File keytabFile = new File(request.getKeytabFilePath());
        if (!keytabFile.exists()) {
            return Response.error("keytab文件不存在");
        }
        System.setProperty("java.security.krb5.conf", configPath + File.separator + KRB5_CONF_FILE_NAME);
        System.setProperty("sun.security.krb5.debug", "true");
        Map<String, String> options = new Hashtable<>();
        options.put("useKeyTab", "true");
        options.put("keyTab", request.getKeytabFilePath());
        options.put("storeKey", "true");
        options.put("principal", request.getPrincipal());
        options.put("refreshKrb5Config", "true");
        options.put("useTicketCache", "false");
        options.put("debug", "true");
        LoginContext loginContext = null;
        try {
            Configuration jaasConfig = new Configuration() {
                @Override
                public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                    return new AppConfigurationEntry[]{
                            new AppConfigurationEntry(Krb5LoginModule.class.getName(),
                                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options)
                    };
                }
            };
            loginContext = new LoginContext("com.sun.security.jgss.krb5.initiate", null, null, jaasConfig);
            loginContext.login();
            Subject subject = loginContext.getSubject();
            return checkTicket(subject);
        } catch (LoginException e) {
            log.error("login error: ", e);
            return handleException(e);
        } finally {
            try {
                assert loginContext != null;
                loginContext.logout();
                log.info("loginWithKeytab login success!");
            } catch (LoginException e) {
                log.error("logout error: ", e);
            }
        }
    }

    private static Response checkTicket(Subject subject) {
        log.info("subject: {}", subject);
        if (subject.getPrivateCredentials(KerberosTicket.class).isEmpty()) {
            log.info("kerberos authentication failed");
            return Response.error("kerberos认证失败");
        } else {
            log.info("kerberos authentication succeeded");
            return Response.success();
        }
    }

    private static Response handleException(Exception e) {
        if (e.getCause() != null && e.getCause() instanceof KrbException) {
            KrbException krbException = (KrbException) e.getCause();
            int returnCode = krbException.returnCode();
            log.info("returnCode:{}", returnCode);
            switch (returnCode) {
                case 6:
                    return Response.error("账号不存在");
                case 24:
                    return Response.error("密码不正确");
                default:
                    return Response.error("未知错误");
            }
        }
        return Response.error("kerberos认证失败");
    }

    private static void setCertificate(String keyStorePath) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, KeyManagementException {
        try (FileInputStream fis = new FileInputStream(keyStorePath)) {
            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
            keyStore.load(fis, new String(Base64.getDecoder().decode(KEYSTORE_PASSWORD)).toCharArray());
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            SSLContext.setDefault(sslContext);
        }
    }
}

Msg

package com.example.ldaptest2.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.HashMap;
import java.util.Map;

/**
 * Msg
 *
 * @author:
 * @date: 2020-06-18
 */
@AllArgsConstructor
@Getter
public enum Msg {

    /**
     * 请求类型错误
     */
    SUCCESS(200, "success"), FAILED(20001, "Operation failed"),
    EXCUTE_ERROR(16001, "Service invocation exception, please try again later"),
    UNKNOW_ERROR(16002, "unknown error"),
    PARAM_ERROR(16003, "request param error"),
    DATA_SAVE_FAIL(16004, "data save fail"),
    ID_IS_NOT_EXIST(16005, "id isn't exist"),
    QUERY_RESULT_IS_EMPTY(16006, "request result is null"),
    NAME_IS_EXIST(16007, "name already exist"),
    ID_IS_NOT_EXIST_DATA(16008, "There is no data for the current ID"),
    DATASOURCE_NOT_EXIST(16009, "datasource not exist"),
    JDBC_EXCEPTION(16010, "jdbc connection or search exception"),
    TASK_HAS_BEEN_STOPPED(16011, "task has been stopped");

    private int code;
    private String msg;

    private static final Map<Integer, Msg> MAP = new HashMap<>();

    static {
        for (Msg msgEnum : Msg.values()) {
            MAP.put(msgEnum.code, msgEnum);
        }
    }

    /**
     * 通过code获取枚举
     *
     * @param code
     *            code
     * @return 枚举
     */
    public static Msg getByCode(int code) {
        return MAP.get(code);
    }
}

ADTest测试类

补充说明

部分补充说明:

  • 说明点1:认证方式分2种:一种是用户名+密码登录认证;另一种是用户名+keytab登录认证;
  • 说明点2:AD用户名testuser26,密码Bingo@1993,用户主体testuser26@TESTLDAP.CAT.COM,因为搭建AD环境时生成keytab采用的是主用主体,所以采用用户主体进行登录认证
  • 说明点3:LDAP公钥证书必须上传后缀名为.jks的文件,比如名称为ldap_keystore.jks,在搭建AD环境时生成的导出的其实是xxx.cer的后缀文件,但实际使用的必须是xxx.jks的文件,所以需要输入命令生成。我们采用的是,页面只能上传.cer文件,然后我后端代码执行命令生成.jks文件。
keytool -import -alias ad-server-cert -file /home/ems/ems_file/ldap/ldapServerConfig/ldap_keystore.cer -keystore /home/ems/ems_file/ldap/ldapServerConfig/ldap_keystore.jks -storepass ldap@1993
  • 说明点4:用户主体由用户名+@大写域名方式拼接而成
  • 说明点5:登录认证还需要加载配置文件krb5.conf,改配置文件内容如下,这些其实是安装kerberos时候使用的文件,具体可看我的文章了解每一项意义,Centos7.9安装kerberos
[libdefaults]
    default_realm = TESTLDAP.CAT.COM
    forwardable = true
    permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac des-cbc-crc

[realms]
    TESTLDAP.CAT.COM = {
        kdc = testldap.cat.com
        admin_server = testldap.cat.com
    }

[domain_realm]
    .testldap.cat.com = TESTLDAP.CAT.COM
    testldap.cat.com = TESTLDAP.CAT.COM
  • 说明点6:认证方式解答,之所以“keytab认证方式”失败后再次调用“用户名+密码认证方式”,是因为keytab文件是需要持续更新的,假设你们单位有100人,而你上传的keytab里面只包含50人而未及时更新keytab文件,那么也需要保证所有ldap账户都能登录认证使用项目。
采用先判断keytab文件是否上传
	如果上传了,先采用“keytab认证方式”
		认证成功,则放行访问公司项目首页
		认证失败,再调用“用户名+密码认证方式”
			认证成功,则放行访问公司项目首页
			认证失败,则弹窗报错
	如果未上传,则采用“用户名+密码认证方式”
		认证成功,则放行访问公司项目首页
		认证失败,则弹窗报错

说明点7:想看keytab文件里用户主体都叫啥可以把文件上传任意一台linux环境,然后执行命令

klist -ke  <xx/xxx/ldap.keytab>

在这里插入图片描述
说明点8:代码中的KEYSTORE_PASSWORD 是加密后的,是为了安全考虑,尽量不要使用明文,万一人家监控到你的代码参数,就泄露了。

//kerberos的认证命令密码:明文是ldap@1993
public static final String KEYSTORE_PASSWORD = "bGRhcEAxOTkz";

代码

package com.example.ldaptest2;

import com.example.ldaptest2.entity.LdapLoginRequest;
import com.example.ldaptest2.entity.Response;
import com.sun.security.auth.module.Krb5LoginModule;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.security.krb5.Config;
import sun.security.krb5.KrbException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * AD域登录认证
 */
public class ADTest {
    private static final Logger log = LoggerFactory.getLogger(ADTest.class);
    public static final String LDAP_SERVER1_CONFIG_PATH = "C:\\Users\\211145187\\Desktop\\fsdownload";
    public static final String KERBEROS_KEYTAB_CONFIG_PATH = "C:\\Users\\211145187\\Desktop\\fsdownload\\ldap.keytab";
    public static final String KRB5_CONF_FILE_NAME = "krb5.conf";
    public static final String KEYSTORE_FILE_NAME = "ldap_keystore.jks";
    //kerberos的认证命令密码:明文是ldap@1993
    public static final String KEYSTORE_PASSWORD = "bGRhcEAxOTkz";
    public static final String KEYSTORE_TYPE = "JKS";

    public static void main(String[] args) {
        LdapLoginRequest request = new LdapLoginRequest();
        request.setUsername("testuser26");
        request.setPassword("Bingo@1993");
        request.setPrincipal("testuser26@TESTLDAP.CAT.COM");
        request.setKeytabFilePath(KERBEROS_KEYTAB_CONFIG_PATH);

        File keystoreFile = new File(LDAP_SERVER1_CONFIG_PATH + File.separator + KEYSTORE_FILE_NAME);
        if (keystoreFile.exists()) {
            try {
                setCertificate(LDAP_SERVER1_CONFIG_PATH + File.separator + KEYSTORE_FILE_NAME);
            } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException |
                    KeyManagementException e) {
                log.error("SSL证书加载异常");
                return;
            }
        }
        Response response = null;
        if (StringUtils.isNotBlank(request.getKeytabFilePath())) {
            File keytabFile = new File(request.getKeytabFilePath());
            if (keytabFile.exists()) {
                response = loginWithKeytab(request, LDAP_SERVER1_CONFIG_PATH);
                log.info("response from loginWithKeytab:{}", response);
            } else {
                log.warn("keytab file does not exit");
            }
        }
        if (response != null && response.getCode() == 200) {
            return;
        } else {
            response = loginWithPassword(request, LDAP_SERVER1_CONFIG_PATH);
            log.info("response from loginWithPassword:{}", response);
            return;
        }
    }


    private static class KerberosCallbackHandler implements javax.security.auth.callback.CallbackHandler {
        private final String username;
        private final String password;

        public KerberosCallbackHandler(String username, String password) {
            this.username = username;
            this.password = password;
        }

        @Override
        public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
            for (Callback callback : callbacks) {
                if (callback instanceof NameCallback) {
                    ((NameCallback) callback).setName(username);
                } else if (callback instanceof PasswordCallback) {
                    ((PasswordCallback) callback).setPassword(password.toCharArray());
                } else {
                    throw new UnsupportedCallbackException(callback);
                }
            }
        }
    }

    private void refreshConfig() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<?> configClass = Config.class;
        Field instanceField = configClass.getDeclaredField("instance");
        instanceField.setAccessible(true);
        instanceField.set(null, null);
        Method refreshMethod = configClass.getDeclaredMethod("refresh");
        refreshMethod.setAccessible(true);
        refreshMethod.invoke(null);
    }

    private static Response loginWithPassword(LdapLoginRequest request, String configPath) {
        try {
            sun.security.krb5.Config.refresh();
//            refreshConfig();
        } catch (KrbException e) {
            log.error("refresh config error", e);
        }
        System.setProperty("java.security.krb5.conf", configPath + File.separator + KRB5_CONF_FILE_NAME);
        System.setProperty("sun.security.krb5.debug", "true");

        LoginContext loginContext = null;
        try {
            loginContext = new LoginContext("com.sun.security.jgss.krb5.initiate", null, new KerberosCallbackHandler(request.getUsername(), request.getPassword()),
                    new Configuration() {
                        @Override
                        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                            Map<String, String> options = new HashMap<>();
                            options.put("useKeyTab", "false");
                            options.put("useTicketCache", "false");
                            options.put("storeKey", "true");
                            options.put("refreshKrb5Config", "true");
                            return new AppConfigurationEntry[]{
                                    new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
                                            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options)
                            };
                        }
                    });
            loginContext.login();
            Subject subject = loginContext.getSubject();
            return checkTicket(subject);
        } catch (LoginException e) {
            log.error("login error: ", e);
            return handleException(e);
        } finally {
            try {
                if (loginContext != null) {
                    loginContext.logout();
                }
                log.info("loginWithPassword login success!");
            } catch (LoginException e) {
                log.error("logout error: ", e);
            }
        }
    }

    private static Response loginWithKeytab(LdapLoginRequest request, String configPath) {
        try {
            sun.security.krb5.Config.refresh();
//            refreshConfig();
        } catch (KrbException e) {
            log.error("refresh config error", e);
        }
        if (StringUtils.isBlank(request.getKeytabFilePath())) {
            return Response.error("非法参数异常");
        }
        File keytabFile = new File(request.getKeytabFilePath());
        if (!keytabFile.exists()) {
            return Response.error("keytab文件不存在");
        }
        System.setProperty("java.security.krb5.conf", configPath + File.separator + KRB5_CONF_FILE_NAME);
        System.setProperty("sun.security.krb5.debug", "true");
        Map<String, String> options = new Hashtable<>();
        options.put("useKeyTab", "true");
        options.put("keyTab", request.getKeytabFilePath());
        options.put("storeKey", "true");
        options.put("principal", request.getPrincipal());
        options.put("refreshKrb5Config", "true");
        options.put("useTicketCache", "false");
        options.put("debug", "true");
        LoginContext loginContext = null;
        try {
            Configuration jaasConfig = new Configuration() {
                @Override
                public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                    return new AppConfigurationEntry[]{
                            new AppConfigurationEntry(Krb5LoginModule.class.getName(),
                                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options)
                    };
                }
            };
            loginContext = new LoginContext("com.sun.security.jgss.krb5.initiate", null, null, jaasConfig);
            loginContext.login();
            Subject subject = loginContext.getSubject();
            return checkTicket(subject);
        } catch (LoginException e) {
            log.error("login error: ", e);
            return handleException(e);
        } finally {
            try {
                assert loginContext != null;
                loginContext.logout();
                log.info("loginWithKeytab login success!");
            } catch (LoginException e) {
                log.error("logout error: ", e);
            }
        }
    }

    private static Response checkTicket(Subject subject) {
        log.info("subject: {}", subject);
        if (subject.getPrivateCredentials(KerberosTicket.class).isEmpty()) {
            log.info("kerberos authentication failed");
            return Response.error("kerberos认证失败");
        } else {
            log.info("kerberos authentication succeeded");
            return Response.success();
        }
    }

    private static Response handleException(Exception e) {
        if (e.getCause() != null && e.getCause() instanceof KrbException) {
            KrbException krbException = (KrbException) e.getCause();
            int returnCode = krbException.returnCode();
            log.info("returnCode:{}", returnCode);
            switch (returnCode) {
                case 6:
                    return Response.error("账号不存在");
                case 24:
                    return Response.error("密码不正确");
                default:
                    return Response.error("未知错误");
            }
        }
        return Response.error("kerberos认证失败");
    }

    private static void setCertificate(String keyStorePath) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, KeyManagementException {
        try (FileInputStream fis = new FileInputStream(keyStorePath)) {
            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
            keyStore.load(fis, new String(Base64.getDecoder().decode(KEYSTORE_PASSWORD)).toCharArray());
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            SSLContext.setDefault(sslContext);
        }
    }
}

四、认证结果

认证成功

E:\Java8\jdk1.8.0_192\bin\java.exe "-javaagent:E:\JetBrains\IntelliJ IDEA 2020.3.1\lib\idea_rt.jar=10827:E:\JetBrains\IntelliJ IDEA 2020.3.1\bin" -Dfile.encoding=UTF-8 -classpath E:\Java8\jdk1.8.0_192\jre\lib\charsets.jar;E:\Java8\jdk1.8.0_192\jre\lib\deploy.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\access-bridge-64.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\cldrdata.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\dnsns.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\jaccess.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\jfxrt.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\localedata.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\nashorn.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\sunec.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\sunjce_provider.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\sunmscapi.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\sunpkcs11.jar;E:\Java8\jdk1.8.0_192\jre\lib\ext\zipfs.jar;E:\Java8\jdk1.8.0_192\jre\lib\javaws.jar;E:\Java8\jdk1.8.0_192\jre\lib\jce.jar;E:\Java8\jdk1.8.0_192\jre\lib\jfr.jar;E:\Java8\jdk1.8.0_192\jre\lib\jfxswt.jar;E:\Java8\jdk1.8.0_192\jre\lib\jsse.jar;E:\Java8\jdk1.8.0_192\jre\lib\management-agent.jar;E:\Java8\jdk1.8.0_192\jre\lib\plugin.jar;E:\Java8\jdk1.8.0_192\jre\lib\resources.jar;E:\Java8\jdk1.8.0_192\jre\lib\rt.jar;G:\WorkSpace\ldap-test2\target\test-classes;G:\WorkSpace\ldap-test2\target\classes;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-starter-web\1.4.7.RELEASE\spring-boot-starter-web-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-starter\1.4.7.RELEASE\spring-boot-starter-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot\1.4.7.RELEASE\spring-boot-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-autoconfigure\1.4.7.RELEASE\spring-boot-autoconfigure-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-starter-logging\1.4.7.RELEASE\spring-boot-starter-logging-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\ch\qos\logback\logback-classic\1.1.11\logback-classic-1.1.11.jar;E:\apache-maven-3.6.3\repository\ch\qos\logback\logback-core\1.1.11\logback-core-1.1.11.jar;E:\apache-maven-3.6.3\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;E:\apache-maven-3.6.3\repository\org\slf4j\log4j-over-slf4j\1.7.25\log4j-over-slf4j-1.7.25.jar;E:\apache-maven-3.6.3\repository\org\yaml\snakeyaml\1.17\snakeyaml-1.17.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-starter-tomcat\1.4.7.RELEASE\spring-boot-starter-tomcat-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.15\tomcat-embed-core-8.5.15.jar;E:\apache-maven-3.6.3\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.15\tomcat-embed-el-8.5.15.jar;E:\apache-maven-3.6.3\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.15\tomcat-embed-websocket-8.5.15.jar;E:\apache-maven-3.6.3\repository\org\hibernate\hibernate-validator\5.2.5.Final\hibernate-validator-5.2.5.Final.jar;E:\apache-maven-3.6.3\repository\javax\validation\validation-api\1.1.0.Final\validation-api-1.1.0.Final.jar;E:\apache-maven-3.6.3\repository\org\jboss\logging\jboss-logging\3.3.1.Final\jboss-logging-3.3.1.Final.jar;E:\apache-maven-3.6.3\repository\com\fasterxml\classmate\1.3.3\classmate-1.3.3.jar;E:\apache-maven-3.6.3\repository\com\fasterxml\jackson\core\jackson-databind\2.8.8\jackson-databind-2.8.8.jar;E:\apache-maven-3.6.3\repository\com\fasterxml\jackson\core\jackson-annotations\2.8.8\jackson-annotations-2.8.8.jar;E:\apache-maven-3.6.3\repository\com\fasterxml\jackson\core\jackson-core\2.8.8\jackson-core-2.8.8.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-web\4.3.9.RELEASE\spring-web-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-webmvc\4.3.9.RELEASE\spring-webmvc-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\projectlombok\lombok\1.18.22\lombok-1.18.22.jar;E:\apache-maven-3.6.3\repository\junit\junit\4.13\junit-4.13.jar;E:\apache-maven-3.6.3\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-starter-test\1.4.7.RELEASE\spring-boot-starter-test-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-test\1.4.7.RELEASE\spring-boot-test-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-test-autoconfigure\1.4.7.RELEASE\spring-boot-test-autoconfigure-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\com\jayway\jsonpath\json-path\2.2.0\json-path-2.2.0.jar;E:\apache-maven-3.6.3\repository\net\minidev\json-smart\2.2.1\json-smart-2.2.1.jar;E:\apache-maven-3.6.3\repository\net\minidev\accessors-smart\1.1\accessors-smart-1.1.jar;E:\apache-maven-3.6.3\repository\org\ow2\asm\asm\5.0.3\asm-5.0.3.jar;E:\apache-maven-3.6.3\repository\org\assertj\assertj-core\2.5.0\assertj-core-2.5.0.jar;E:\apache-maven-3.6.3\repository\org\mockito\mockito-core\1.10.19\mockito-core-1.10.19.jar;E:\apache-maven-3.6.3\repository\org\objenesis\objenesis\2.1\objenesis-2.1.jar;E:\apache-maven-3.6.3\repository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;E:\apache-maven-3.6.3\repository\org\skyscreamer\jsonassert\1.3.0\jsonassert-1.3.0.jar;E:\apache-maven-3.6.3\repository\org\json\json\20140107\json-20140107.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-core\4.3.9.RELEASE\spring-core-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-test\4.3.9.RELEASE\spring-test-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-starter-security\1.4.7.RELEASE\spring-boot-starter-security-1.4.7.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-aop\4.3.9.RELEASE\spring-aop-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\security\spring-security-config\4.1.4.RELEASE\spring-security-config-4.1.4.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\security\spring-security-web\4.1.4.RELEASE\spring-security-web-4.1.4.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\boot\spring-boot-starter-data-ldap\2.6.3\spring-boot-starter-data-ldap-2.6.3.jar;E:\apache-maven-3.6.3\repository\org\springframework\data\spring-data-ldap\2.6.3\spring-data-ldap-2.6.3.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-context\4.3.9.RELEASE\spring-context-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\data\spring-data-commons\1.12.11.RELEASE\spring-data-commons-1.12.11.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\slf4j\jcl-over-slf4j\1.7.25\jcl-over-slf4j-1.7.25.jar;E:\apache-maven-3.6.3\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;E:\apache-maven-3.6.3\repository\com\sun\ldapbp\1.0\ldapbp-1.0.jar;E:\apache-maven-3.6.3\repository\org\springframework\ldap\spring-ldap-core\2.4.0\spring-ldap-core-2.4.0.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-beans\4.3.9.RELEASE\spring-beans-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-tx\4.3.9.RELEASE\spring-tx-4.3.9.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\apache\directory\api\api-all\2.0.0\api-all-2.0.0.jar;E:\apache-maven-3.6.3\repository\org\apache\servicemix\bundles\org.apache.servicemix.bundles.xpp3\1.1.4c_7\org.apache.servicemix.bundles.xpp3-1.1.4c_7.jar;E:\apache-maven-3.6.3\repository\org\apache\servicemix\bundles\org.apache.servicemix.bundles.dom4j\2.1.1_1\org.apache.servicemix.bundles.dom4j-2.1.1_1.jar;E:\apache-maven-3.6.3\repository\org\apache\commons\commons-pool2\2.4.2\commons-pool2-2.4.2.jar;E:\apache-maven-3.6.3\repository\org\apache\mina\mina-core\2.1.3\mina-core-2.1.3.jar;E:\apache-maven-3.6.3\repository\org\apache\commons\commons-lang3\3.9\commons-lang3-3.9.jar;E:\apache-maven-3.6.3\repository\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar;E:\apache-maven-3.6.3\repository\org\apache\servicemix\bundles\org.apache.servicemix.bundles.antlr\2.7.7_5\org.apache.servicemix.bundles.antlr-2.7.7_5.jar;E:\apache-maven-3.6.3\repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;E:\apache-maven-3.6.3\repository\org\springframework\security\kerberos\spring-security-kerberos-core\1.0.1.RELEASE\spring-security-kerberos-core-1.0.1.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\security\kerberos\spring-security-kerberos-client\1.0.1.RELEASE\spring-security-kerberos-client-1.0.1.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\apache\httpcomponents\httpclient\4.5.3\httpclient-4.5.3.jar;E:\apache-maven-3.6.3\repository\org\apache\httpcomponents\httpcore\4.4.6\httpcore-4.4.6.jar;E:\apache-maven-3.6.3\repository\org\springframework\security\kerberos\spring-security-kerberos-web\1.0.1.RELEASE\spring-security-kerberos-web-1.0.1.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\security\spring-security-ldap\4.2.3.RELEASE\spring-security-ldap-4.2.3.RELEASE.jar;E:\apache-maven-3.6.3\repository\org\springframework\security\spring-security-core\4.2.3.RELEASE\spring-security-core-4.2.3.RELEASE.jar;E:\apache-maven-3.6.3\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;E:\apache-maven-3.6.3\repository\org\springframework\spring-expression\4.3.9.RELEASE\spring-expression-4.3.9.RELEASE.jar com.example.ldaptest2.ADTest
Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt false ticketCache is null isInitiator true KeyTab is C:\Users\211145187\Desktop\fsdownload\ldap.keytab refreshKrb5Config is true principal is testuser26@TESTLDAP.CAT.COM tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Refreshing Kerberos configuration
principal is testuser26@TESTLDAP.CAT.COM
Will use keytab
Commit Succeeded 

10:41:07.376 [main] INFO com.example.ldaptest2.ADTest - subject: 主体: 
	主用户: testuser26@TESTLDAP.CAT.COM
	专用身份证明: Ticket (hex) = 
0000: 61 82 04 52 30 82 04 4E   A0 03 02 01 05 A1 12 1B  a..R0..N........
0010: 10 54 45 53 54 4C 44 41   50 2E 43 41 54 2E 43 4F  .TESTLDAP.CAT.CO
0020: 4D A2 25 30 23 A0 03 02   01 02 A1 1C 30 1A 1B 06  M.%0#.......0...
0030: 6B 72 62 74 67 74 1B 10   54 45 53 54 4C 44 41 50  krbtgt..TESTLDAP
0040: 2E 43 41 54 2E 43 4F 4D   A3 82 04 0A 30 82 04 06  .CAT.COM....0...
0050: A0 03 02 01 12 A1 03 02   01 02 A2 82 03 F8 04 82  ................
0060: 03 F4 32 37 7A 5F 23 6B   5A CB 5D 22 91 95 E5 B8  ..27z_#kZ.]"....
0070: 31 07 0F B2 DA F9 F8 FE   8F B5 90 FE D1 AD 70 4A  1.............pJ
0080: 0B D9 8C 5C 4A 01 D7 54   B2 94 7B 46 E6 D2 C7 EA  ...\J..T...F....
0090: C2 B2 A1 A1 C6 70 2B EC   E5 A7 AB 4F 3A 80 A6 CB  .....p+....O:...
00A0: 37 1A 9C AF 19 7F 68 A4   65 9A 8D 53 AF 36 D9 F5  7.....h.e..S.6..
00B0: F2 F4 E0 50 0A EC F3 FA   13 77 44 50 C9 1F E5 31  ...P.....wDP...1
00C0: 64 A4 A4 33 34 D0 C9 B4   D0 C9 97 61 D8 A1 C6 D1  d..34......a....
00D0: 47 3E 03 AE CE E1 9B 91   80 06 22 63 61 37 98 D3  G>........"ca7..
00E0: 64 70 8D 03 0B D1 FD 23   3B B6 AF 08 03 82 8B D3  dp.....#;.......
00F0: 08 AE 9C FE DE 81 3F C4   37 18 B3 A6 F8 CC CC 8D  ......?.7.......
0100: EE E7 3B 26 23 58 E2 1D   91 CD 07 81 AE A4 88 13  ..;&#X..........
0110: F0 D6 28 9D 4D 56 F3 80   D2 9C 07 41 DE 62 2E 8F  ..(.MV.....A.b..
0120: F7 89 F8 70 1E B1 0A FE   20 0E 07 81 19 06 C8 71  ...p.... ......q
0130: 3B D5 6B 98 C7 24 52 A0   DF 0E D2 02 EB 52 32 EF  ;.k..$R......R2.
0140: 42 2F 14 31 BF 29 FB ED   CB 62 2A AD D5 EA BD FD  B/.1.)...b*.....
0150: A6 ED A6 7E EC 55 2F F7   4C CA D7 9D E7 17 A0 2B  .....U/.L......+
0160: 36 B2 46 CB 8D D9 2C 97   97 EA C7 CA 75 30 AA 3B  6.F...,.....u0.;
0170: DD 3F 37 2E 1E 73 34 08   66 26 BF 45 D1 7E D1 99  .?7..s4.f&.E....
0180: 56 0A 4A 81 7C 15 0A 83   EB BF B3 17 F0 9C 35 C8  V.J...........5.
0190: 9A 3A 98 FD CF B9 DF 2D   2A 84 32 8B 5E D3 92 41  .:.....-*.2.^..A
01A0: 00 DF 21 D2 4F 0A 81 7A   64 E2 50 9F 9D 89 EB F1  ..!.O..zd.P.....
01B0: B3 63 4B 49 59 E8 C3 AB   97 DD 4F FA 6C 68 B1 DD  .cKIY.....O.lh..
01C0: B9 E1 5D F0 E4 49 88 D3   00 11 4C 20 A8 54 AD CC  ..]..I....L .T..
01D0: BF 52 17 FC DB 91 26 F7   59 A5 5C 6D 26 C2 78 C2  .R....&.Y.\m&.x.
01E0: EA 9E 6D CB 92 47 F5 0B   8F 10 08 95 24 DD 91 49  ..m..G......$..I
01F0: 18 45 58 BE 10 95 7F 08   71 E0 81 2E 3F 94 72 99  .EX.....q...?.r.
0200: 2C 8D D1 A7 DA 80 12 95   6D A0 4E 4B CA D9 D6 54  ,.......m.NK...T
0210: 74 63 F0 BE 9B E1 1C 8C   9E C5 A0 4E CD A9 DD 82  tc.........N....
0220: C3 BD 8C E2 70 08 6F 1E   01 F5 8A 01 90 FF CA 0A  ....p.o.........
0230: 64 FB 03 C6 88 30 C9 65   CB 81 49 C1 5C 82 BB E6  d....0.e..I.\...
0240: 72 07 A9 D5 7A EC 31 1E   40 51 DB DD 21 D0 A9 80  r...z.1.@Q..!...
0250: DF 41 A8 D1 F6 94 7C 7D   CE 0D 9B 76 2F FD E6 13  .A.........v/...
0260: 81 04 51 04 2D 80 37 A6   75 51 CF 1D E9 D4 0F 22  ..Q.-.7.uQ....."
0270: E0 FB 02 08 76 96 35 25   45 CC A7 35 AB 8B 23 05  ....v.5%E..5..#.
0280: 80 1D EC B4 BD A8 A6 AB   E4 64 DC D7 40 8D 7C 4A  .........d..@..J
0290: FC 7A D6 83 02 E9 96 52   83 9A F1 7D 85 F4 66 A0  .z.....R......f.
02A0: 71 AB AB F2 CB 99 A7 25   69 C1 86 69 84 A2 E9 D7  q......%i..i....
02B0: 07 93 77 CA 3A 0F 16 36   4C 86 E4 F1 5E 21 A3 AD  ..w.:..6L...^!..
02C0: CD 02 DA A5 DC 30 88 6B   F9 59 24 E9 C1 5C D1 35  .....0.k.Y$..\.5
02D0: 7E 6D 8D E1 73 BF BE 36   26 7E 5B 89 57 6E FB 97  .m..s..6&.[.Wn..
02E0: AB 99 B1 2F B3 EC 01 79   B7 11 06 19 97 7F 1F 11  .../...y........
02F0: C7 8D 7A 03 28 75 73 FF   2C 9B F7 0F 6E CC 7E DD  ..z.(us.,...n...
0300: F2 E4 9C A2 E6 3C C6 AC   48 C7 4C 38 67 94 E5 DD  .....<..H.L8g...
0310: CC A9 97 3B 7B 27 58 ED   9F D1 F1 FB 63 1F D8 E8  ...;.'X.....c...
0320: 6C F2 73 8D C2 50 3E D9   79 40 E8 F5 C1 75 04 1B  l.s..P>.y@...u..
0330: 0E 40 37 6F AC CD 96 00   3B C9 AA D3 F1 D0 D2 3A  .@7o....;......:
0340: C2 7E 0D A1 CC 18 4E C6   D9 A8 6D DA D8 F4 84 6E  ......N...m....n
0350: A5 9B 35 D7 A2 64 27 3C   3B 93 A9 61 86 94 6B D6  ..5..d'<;..a..k.
0360: 5E 0D B6 31 78 1D A6 83   E1 84 C3 90 1B 33 E4 E1  ^..1x........3..
0370: 6D DF 13 C1 88 B8 7F B9   FD 01 3A 49 32 5D F0 00  m.........:I2]..
0380: D9 53 97 CE 6F B0 A3 C8   64 A2 57 32 1B F7 2C 0D  .S..o...d.W2..,.
0390: EC 0E 1E 06 52 14 EA 7F   47 25 E5 4C AC 95 8D 72  ....R...G%.L...r
03A0: 31 28 A4 A7 8B F4 00 11   AB A1 9D D9 B4 B4 A4 DB  1(..............
03B0: 2A 82 75 8F EA 8E 9E 44   3D D5 23 9E C5 86 8F 81  *.u....D=.#.....
03C0: B9 3C 01 95 31 25 ED 48   26 A5 4F 91 E5 C9 AF 87  .<..1%.H&.O.....
03D0: 0E 5C B6 71 9C 82 9D 02   FA 3E 6B B5 C2 1E FE F2  .\.q.....>k.....
03E0: 32 33 54 39 A9 8B EB F1   82 1A 7E 27 11 D4 FD 2E  23T9.......'....
03F0: 37 5D 03 3B 05 D3 09 51   0F 70 9A 43 E1 44 45 1F  7].;...Q.p.C.DE.
0400: 16 48 69 64 07 E7 9E F9   28 36 4E 6F B6 97 2A EF  .Hid....(6No..*.
0410: 22 7C 2E 62 82 03 3C C2   97 D2 D0 C9 04 D0 78 00  "..b..<.......x.
0420: B9 2B 66 CA 3C F5 D1 07   50 B3 2E 0D 4B 15 1A AD  .+f.<...P...K...
0430: B8 9F 4B 54 55 C1 BC 3C   5C 1A BF 63 A4 C4 65 93  ..KTU..<\..c..e.
0440: CA 4D 9E 2C 56 33 A1 43   7A 15 B8 26 6E 4D DD A2  .M.,V3.Cz..&nM..
0450: C6 BC 5B 48 72 C7                                  ..[Hr.

Client Principal = testuser26@TESTLDAP.CAT.COM
Server Principal = krbtgt/TESTLDAP.CAT.COM@TESTLDAP.CAT.COM
Session Key = EncryptionKey: keyType=18 keyBytes (hex dump)=
0000: 76 A5 11 BD 7B B4 8B 9A   B4 7B 2D F8 F2 4D 28 62  v.........-..M(b
0010: 89 E4 5F 92 3E C3 61 C5   28 39 63 D2 96 D6 CA FA  .._.>.a.(9c.....


Forwardable Ticket true
Forwarded Ticket false
Proxiable Ticket false
Proxy Ticket false
Postdated Ticket false
Renewable Ticket false
Initial Ticket false
Auth Time = Fri Jul 05 10:41:07 CST 2024
Start Time = Fri Jul 05 10:41:07 CST 2024
End Time = Fri Jul 05 20:41:07 CST 2024
Renew Till = null
Client Addresses  Null 
	专用身份证明: C:\Users\211145187\Desktop\fsdownload\ldap.keytab for testuser26@TESTLDAP.CAT.COM

10:41:07.395 [main] INFO com.example.ldaptest2.ADTest - kerberos authentication succeeded
		[Krb5LoginModule]: Entering logout
		[Krb5LoginModule]: logged out Subject
10:41:07.398 [main] INFO com.example.ldaptest2.ADTest - loginWithKeytab login success!
10:41:07.398 [main] INFO com.example.ldaptest2.ADTest - response from loginWithKeytab:Response(code=200, msg=success, info=null)

Process finished with exit code 0

认证失败

10:42:38.883 [main] ERROR com.example.ldaptest2.ADTest - login error: 
10:42:38.884 [main] INFO com.example.ldaptest2.ADTest - returnCode:6
10:42:38.889 [main] INFO com.example.ldaptest2.ADTest - loginWithPassword login success!
10:42:38.889 [main] INFO com.example.ldaptest2.ADTest - response from loginWithPassword:Response(code=20001, msg=账号不存在, info=null)

本人其他相关文章链接

1.Centos7.9安装openldap
2.Centos7.9安装kerberos
3.Openldap集成Kerberos
4.Centos7.9安装phpldapadmin
5.java连接ldap实现用户查询功能
6.java连接kerberos用户认证
7.javax.security.auth.login.LoginException: Unable to obtain password from user
8.javax.security.auth.login.LoginException: null (68)
9.javax.security.auth.login.LoginException: Message stream modified (41)
10.javax.security.auth.login.LoginException: Checksum failed
11.javax.security.auth.login.LoginException: No CallbackHandler available to garner authentication info
12.javax.security.auth.login.LoginException: Cannot locate KDC
13.javax.security.auth.login.LoginException: Receive timed out
14.java: 无法访问org.springframework.context.ConfigurableApplicationContext
15.LDAP: error code 34 - invalid DN
16.LDAP: error code 32 - No Such Object
17.java: 无法访问org.springframework.ldap.core.LdapTemplate

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1896547.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

洗地机品牌哪个最好用?硬核推荐五大实力爆款洗地机

在这个忙碌的时代&#xff0c;家就是我们放松的港湾&#xff0c;但要保持它的清洁与舒适常常很不容易。每天拖着疲惫的身体回家&#xff0c;还要面对地板上那些难缠的灰尘、污渍&#xff0c;真是非常让人头疼。不过&#xff0c;洗地机的出现就像是给家务清洁装上了智能引擎&…

14270-02G 同轴连接器

型号简介 14270-02G是Southwest Microwave的2.4 mm 同轴连接器。这款连接器连接器采用不锈钢、铍铜合金、黄铜合金和 ULTEM 1000 等高质量材料&#xff0c;可能具有更好的耐腐蚀性、导电性和机械强度。金镀层可以提供更低的接触电阻和更好的耐腐蚀性。 型号特点 电缆的中心导体…

NSSCTF-Web题目23(RCE-空格绕过)

目录 [SWPUCTF 2022 新生赛]webdog1__start 1、题目 2、知识点 3、思路 [FSCTF 2023]webshell是啥捏 4、题目 5、知识点 6、思路 [SWPUCTF 2022 新生赛]webdog1__start 1、题目 2、知识点 RCE、空格绕过&#xff0c;嵌套eval 3、思路 出现这个页面&#xff0c;没有其…

Linux系统部署MongoDB开源文档型数据库并实现无公网IP远程访问

文章目录 前言1. 安装Docker2. 使用Docker拉取MongoDB镜像3. 创建并启动MongoDB容器4. 本地连接测试5. 公网远程访问本地MongoDB容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&am…

ggrcs包4.0版本发布—重新对密度图宽度进行了设计

目前本人写的ggrcs包新的4.0版本已经在CRAN上线&#xff0c;目前支持逻辑回归&#xff08;logistic回归&#xff09;、cox回归和多元线性回归。 需要的可以使用代码安装 install.packages("ggrcs")如果原来安装了旧版本&#xff0c;重新在安装一次就可以升级到新版…

Android --- Service

出自于此&#xff0c;写得很清楚。关于Android Service真正的完全详解&#xff0c;你需要知道的一切_android service-CSDN博客 出自【zejian的博客】 什么是Service? Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。 服务可由其他应用组件…

AI技术在招聘行业的应用

大模型AI技术在招聘行业的应用正变得越来越广泛&#xff0c;以下是一些关键领域的应用实例。大模型AI技术在招聘行业的应用不仅提高了效率和精确度&#xff0c;还帮助企业在竞争激烈的人才市场中获得优势。随着技术的不断发展&#xff0c;预计AI将在招聘领域扮演更加重要的角色…

grpc-go客户端接口添加

【1】 proto相关文件同服务端&#xff0c;如已经生成&#xff0c;可以直接使用服务端的文件&#xff08;包&#xff09; 【2】新建一个目录“WHG_CLIENT”&#xff0c;目录下新建一个main.go文件 package mainimport ("context""log""grpc-go-maste…

小程序新版获取用户头像、昵称调整方案

目录 前言调整背景调整说明低版本兼容处理参考代码WXMLWXSSJS补充及优化图像上传Java版图像上传接口.Net版图像上传接口前言 调整背景 由于 PC/macOS 平台「头像昵称填写能力」存在兼容性问题,对于来自低于2.27.1版本的访问,小程序通过 wx.getUserProfile 接口将正常返回用户…

23.【C语言】循环结构之while

接第11篇 格式&#xff1a;while (表达式)//加括号代表如果表达式为真&#xff0c;执行循环 { } 根据需要&#xff0c;可以在代码块中加break;提前跳出循环&#xff08;永久终止&#xff09; 而continue;是跳出本次循环&#xff0c;进入while循环的判断部分&#xff0c;决定是…

c++ 设计模式 的课本范例(下)

&#xff08;19&#xff09; 桥接模式 Bridge&#xff0c;不是采用类继承&#xff0c;而是采用类组合&#xff0c;一个类的数据成员是类对象&#xff0c;来扩展类的功能。源码如下&#xff1a; class OS // 操作系统负责绘图 { public:virtual ~OS() {}virtual void draw(cha…

C++ thread线程库

thread库 std::thread 是 C 标准库中的一个类&#xff0c;用于管理和控制单个执行线程。线程允许程序并行执行多个函数&#xff0c;从而提高性能和响应速度。std::thread 类提供了一种便捷的方式来创建和操作线程。 1、用途 并行执行任务&#xff1a; 通过 std::thread&…

守护家庭的安全卫士:家用可燃气体探测器

在这个追求智能与安全并重的时代&#xff0c;每一个细微之处的防护都显得尤为重要&#xff0c;尤其是在我们最为依赖的家庭空间里。当谈及家居安全&#xff0c;燃气安全无疑占据着至关重要的位置。据统计&#xff0c;每年因燃气管老化、连接处松动等问题引发燃气泄漏的事故不在…

外泌体相关基因肝癌临床模型预测——2-3分纯生信文章复现——4.预后相关外泌体基因确定单因素cox回归(2)

内容如下&#xff1a; 1.外泌体和肝癌TCGA数据下载 2.数据格式整理 3.差异表达基因筛选 4.预后相关外泌体基因确定 5.拷贝数变异及突变图谱 6.外泌体基因功能注释 7.LASSO回归筛选外泌体预后模型 8.预后模型验证 9.预后模型鲁棒性分析 10.独立预后因素分析及与临床的…

STM32-HAL-FATFS(文件系统)(没做完,stm32f103zet6(有大佬的可以在评论区说一下次板子为什么挂载失败了))

1STM32Cube配置 1-1配置时钟 1-2配置调试端口 1-3配置uart 1-4配置SDIO&#xff08;注意参数&#xff09;&#xff08;其中他的初始化的异常函数给注释&#xff0c;SD卡文件写了&#xff09; 配置了还要打开中断和DMA可在我的其他文章中看一样的 1-5配置FatFs (只改了图选中…

Unity 资源 之 Sweet Cakes Icon套装,110个高品质蛋糕图标分享

Sweet Cakes Icon 套装 - 为 Unity 开发者带来甜蜜惊喜 前言资源包内容领取兑换码 前言 亲爱的 Unity 开发者们&#xff0c;今天要向你们介绍一款令人心动的图标套装 - Sweet Cakes Icon。 Sweet Cakes Icon 套装包含了超过 110 种高品质的蛋糕和纸杯蛋糕图标&#xff0c;这无…

累积分布函数的一些性质证明

性质1&#xff1a; E [ X ] ∫ 0 ∞ ( 1 − F ( x ) ) d x − ∫ − ∞ 0 F ( x ) d x ( 1 ) E[X]\int_0^{\infty}(1-F(x))dx - \int_{-\infty}^0F(x)dx\quad (1) E[X]∫0∞​(1−F(x))dx−∫−∞0​F(x)dx(1) 证明&#xff1a; E [ X ] ∫ − ∞ ∞ x p ( x ) d x E[X] …

一个人的开发团队:前后端与调动AI

作为一名大数据开发者&#xff0c;我对 AI 的应用感兴趣&#xff0c;但平常都是处理数据&#xff0c;对应前后端代码不擅长&#xff0c;幸好有了 AI&#xff0c;在 AI 的帮助下能写出很多前后端代码了。 目录 前端开发后端开发调用AI整合前后端与AI 本文将通过一个简单的项目…

GO语言入门之准备

一、Go的简介 1.什么是Go Go 是一个开源的编程语言&#xff0c;最早起源于2007年&#xff0c;在2009年正式对外发布&#xff0c;Go 语言被设计成一门应用于搭载 Web 服务器&#xff0c;存储集群或类似用途的巨型中央服务器的系统编程语言。它能让构造简单、可靠且高效的软件变…

国产麒麟v10、UOS系统在线比较两个Word文件的内容差异

调用PageOffice的WordCompare方法&#xff0c;同时在线打开两个Word文档&#xff0c;可以切换显示其中的一个文档&#xff0c;或者显示两个文档的对比结果&#xff0c;即可实现在线的文档内容比较功能。此功能可以应用在以下方面&#xff1a; 文档管理中&#xff0c;比较两个版…