使用不带服务器名的LDAP从Java(Linux)到Active Directory进行身份验证
我们的开发人员在Linux上使用Java做各种事情(比如检查组成员等)。它能工作-没问题 问题是他们在代码中硬编码了我们的域控制器(LDAP服务器)的服务器名。所以现在,当我们需要用更新的DCs替换它们时,它们需要更改代码 Active Directory本质上是冗余的。域名(例如:domain.local)是可用于我们广告的所有DC:s的循环 开发人员有没有办法不指定域控制器服务器名称,而只指定Active Directory域名,然后他们的Linux服务器将找到可用的DC:s并使用启动并运行的DC:s使用不带服务器名的LDAP从Java(Linux)到Active Directory进行身份验证,java,linux,active-directory,ldap,Java,Linux,Active Directory,Ldap,我们的开发人员在Linux上使用Java做各种事情(比如检查组成员等)。它能工作-没问题 问题是他们在代码中硬编码了我们的域控制器(LDAP服务器)的服务器名。所以现在,当我们需要用更新的DCs替换它们时,它们需要更改代码 Active Directory本质上是冗余的。域名(例如:domain.local)是可用于我们广告的所有DC:s的循环 开发人员有没有办法不指定域控制器服务器名称,而只指定Active Directory域名,然后他们的Linux服务器将找到可用的DC:s并使用启动并运行
欢迎提供示例/链接。谢谢 显然,服务器名称至少应该是可配置的,而不是硬编码到应用程序中 但是,您应该能够通过查找特殊的DNS记录来找到服务器,即
\u ldap.\u tcp.DOMAINNAME
的SRV记录。linux服务器必须配置为使用与广告更新相同的DNS服务器
要确定这是否可行,请在linux服务器上运行命令host-tsrv\u ldap.\u tcp.DOMAINNAME
请参阅还提供了有关如何在java中查找SRV记录的一些信息,我们使用以下代码在大量系统上工作:
/**
* Detect the default LDAP server
* @return server:port or null
*/
String getDefaultLdapHost() {
try {
Hashtable<String, String> env = new Hashtable();
env.put( "java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory" );
DirContext dns = new InitialDirContext( env );
InetAddress address = InetAddress.getLocalHost();
String domain = address.getCanonicalHostName();
if( domain.equals( address.getHostAddress() ) ) {
//domain is a ip address
domain = getDnsPtr( dns );
}
int idx = domain.indexOf( '.' );
if( idx < 0 ) {
//computer is not in a domain? We will look in the DNS self.
domain = getDnsPtr( dns );
idx = domain.indexOf( '.' );
if( idx < 0 ) {
//computer is not in a domain
return null;
}
}
domain = domain.substring( idx + 1 );
Attributes attrs = dns.getAttributes( "_ldap._tcp." + domain, new String[] { "SRV" } );
Attribute attr = attrs.getAll().nextElement();
String srv = attr.get().toString();
String[] parts = srv.split( " " );
return parts[3] + ":" + parts[2];
} catch( Exception ex ) {
ex.printStackTrace();
return null;
}
}
/**
* Look for a reverse PTR record on any available ip address
* @param dns DNS context
* @return the PTR value
* @throws Exception if the PTR entry was not found
*/
private String getDnsPtr( DirContext dns ) throws Exception {
Exception exception = null;
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while(interfaces.hasMoreElements()) {
NetworkInterface nif = interfaces.nextElement();
if( nif.isLoopback() ) {
continue;
}
Enumeration<InetAddress> adresses = nif.getInetAddresses();
while(adresses.hasMoreElements()) {
InetAddress address = adresses.nextElement();
if( address.isLoopbackAddress() || address instanceof Inet6Address) {
continue;
}
String domain = address.getCanonicalHostName();
if( !domain.equals( address.getHostAddress() ) && (domain.indexOf( '.' ) > 0) ) {
return domain;
}
String ip = address.getHostAddress();
String[] digits = ip.split( "\\." );
StringBuilder builder = new StringBuilder();
builder.append( digits[3] ).append( '.' );
builder.append( digits[2] ).append( '.' );
builder.append( digits[1] ).append( '.' );
builder.append( digits[0] ).append( ".in-addr.arpa." );
try {
Attributes attrs = dns.getAttributes( builder.toString(), new String[] { "PTR" } );
return attrs.get( "PTR" ).get().toString();
} catch( Exception ex ) {
exception = ex;
}
}
}
if( exception != null ) {
throw exception;
}
throw new IllegalStateException("No network");
}
/**
*检测默认LDAP服务器
*@return服务器:端口或空
*/
字符串getDefaultLdapHost(){
试一试{
Hashtable env=新的Hashtable();
put(“java.naming.factory.initial”、“com.sun.jndi.dns.DnsContextFactory”);
DirContext dns=新的初始DirContext(env);
InetAddress=InetAddress.getLocalHost();
字符串域=地址。getCanonicalHostName();
if(domain.equals(address.getHostAddress())){
//域是一个ip地址
域=getDnsPtr(dns);
}
int idx=domain.indexOf('.');
if(idx<0){
//计算机不在域中?我们将查看DNS自身。
域=getDnsPtr(dns);
idx=domain.indexOf('.');
if(idx<0){
//计算机不在域中
返回null;
}
}
domain=domain.substring(idx+1);
Attributes attrs=dns.getAttributes(“_ldap._tcp.+domain,新字符串[]{“SRV”});
属性attr=attrs.getAll().nextElement();
字符串srv=attr.get().toString();
String[]parts=srv.split(“”);
退货零件[3]+“:”+零件[2];
}捕获(例外情况除外){
例如printStackTrace();
返回null;
}
}
/**
*在任何可用ip地址上查找反向PTR记录
*@param dns上下文
*@返回PTR值
*@如果找不到PTR条目,则引发异常
*/
私有字符串getDnsPtr(DirContext dns)引发异常{
异常=空;
枚举接口=NetworkInterface.getNetworkInterfaces();
while(interfaces.hasMoreElements()){
NetworkInterface nif=interfaces.nextElement();
if(nif.isLoopback()){
继续;
}
枚举地址=nif.getInetAddresses();
while(address.hasMoreElements()){
InetAddress=address.nextElement();
if(address.isLoopbackAddress()| | Inet6Address的地址实例){
继续;
}
字符串域=地址。getCanonicalHostName();
如果(!domain.equals(address.getHostAddress())&&(domain.indexOf('.')>0)){
返回域;
}
字符串ip=address.getHostAddress();
字符串[]位=ip.split(\\);
StringBuilder=新的StringBuilder();
builder.append(数字[3]).append('.');
builder.append(数字[2]).append('.');
builder.append(数字[1]).append('.');
append(数字[0]).append(“.in addr.arpa.”);
试一试{
Attributes attrs=dns.getAttributes(builder.toString(),新字符串[]{“PTR”});
返回attrs.get(“PTR”).get().toString();
}捕获(例外情况除外){
例外=例外;
}
}
}
if(异常!=null){
抛出异常;
}
抛出新的非法状态异常(“无网络”);
}