Java 使用GSS和通道绑定连接到LDAP
我正在尝试以域用户身份登录的Windows计算机上使用GSS绑定到Active Directory服务器。通常情况下,这很好。但在强制执行签名和绑定时 (见附件) GSS无法绑定。据介绍,这个特性是在JDK16(b18)中添加的,但是我无法成功地绑定失败的错误消息Java 使用GSS和通道绑定连接到LDAP,java,active-directory,ldap,gssapi,java-16,Java,Active Directory,Ldap,Gssapi,Java 16,我正在尝试以域用户身份登录的Windows计算机上使用GSS绑定到Active Directory服务器。通常情况下,这很好。但在强制执行签名和绑定时 (见附件) GSS无法绑定。据介绍,这个特性是在JDK16(b18)中添加的,但是我无法成功地绑定失败的错误消息 javax.naming.AuthenticationException:[LDAP:错误代码49-80090346:LDAPPER:DSID-0C0900595,注释:AcceptSecurityContext错误,数据800903
javax.naming.AuthenticationException:[LDAP:错误代码49-80090346:LDAPPER:DSID-0C0900595,注释:AcceptSecurityContext错误,数据80090346,v3839
其他有关详情:
- 我的公司有3个域控制器,每个都返回相同的错误。 它们当前设置为值=1(受支持时),但值=2 (始终)具有相同的效果
- 我相当肯定我的项目使用的是JDK 16 build 20
- 当使用用户名和密码绑定时,所有操作都按预期进行
- 此外,通过LDAP(而不是LDAPS)进行的绑定也适用于GSS
- 关键的组合是GSS+LDAP
public class ActiveDirectory {
public LdapContext getConnection(boolean ssl) throws NamingException {
return getConnection(null, null, ssl);
}
public LdapContext getConnection(String username, String password, boolean ssl) throws NamingException {
String domainName = "";
try {
String fqdn = java.net.InetAddress.getLocalHost().getCanonicalHostName(); //lookup the domain
if (fqdn.split("\\.").length > 1) {
domainName = fqdn.substring(fqdn.indexOf(".") + 1);
}
} catch (java.net.UnknownHostException e) {
}
Hashtable props = new Hashtable();
if (password != null) {
password = password.trim();
if (password.length() == 0) { //the password was blank. Bind with GSS anyway
password = null;
}
}
if (password != null) { // a password was provided. Bind as that user
String principalName = username + "@" + domainName;
props.put(Context.SECURITY_PRINCIPAL, principalName);
props.put(Context.SECURITY_AUTHENTICATION, "simple");
props.put(Context.SECURITY_CREDENTIALS, password);
} else { //no password. Bind with GSS
String principalName = System.getProperty("user.name") + "@" + domainName;
username=System.getProperty("user.name");
props.put(Context.SECURITY_PRINCIPAL, principalName);
props.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
System.setProperty("sun.security.jgss.native", "true");
}
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
String ldapURL = "";
for (String server : domainControllers) {
if (ssl) { //use SSL to bind
ldapURL = "ldaps://" + server + "." + domainName + "/";
props.put(Context.SECURITY_PROTOCOL, "ssl");
props.put("com.sun.jndi.ldap.tls.cbtype", "tls-server-end-point"); //use channel binding !!! DOESNT WORK WITH GSS. See https://bugs.openjdk.java.net/browse/JDK-8245527?attachmentViewMode=gallery
props.put("com.sun.jndi.ldap.connect.timeout", "2000");
} else { //dont use ssl to bind
ldapURL = "ldap://" + server + "." + domainName + '/';
props.put(Context.SECURITY_PROTOCOL, "");
}
props.put(Context.PROVIDER_URL,ldapURL);
try {
return connect(props);
} catch (NamingException e) {
System.out.println(e.toString());
}
}
throw new NamingException("Failed to authenticate " + username + "@" + domainName);
}
private LdapContext connect(Hashtable props) throws NamingException {
return new InitialLdapContext(props, null);
}
如果有人能发现我做错了什么,那将不胜感激。谢谢!我对LDAP一无所知,所以我只是在猜测,但我注意到其中提到了一些注册表项(请参阅“如何复制”,第2步)。你这样做了吗?@Nicolaipalog提到的注册表项是如何配置windows server以强制执行签名和绑定。它们与客户端无关。