Tomcat 7.0.14 LDAP身份验证

Din*_*son 5 authentication tomcat ldap

我有一个在Tomcat 7.0.14上运行的Web应用程序,我正在使用LDAP进行用户身份验证.问题是当用户在非活动期后登录时会出现以下警告.非活动期不必很长,因为只需几分钟即可.但是,尽管有警告,用户仍可以登录.从用户的角度来看,应用程序运行正常,但Tomcat日志显示下面的警告.

Jun 6, 2012 9:41:19 AM org.apache.catalina.realm.JNDIRealm authenticate  
WARNING: Exception performing authentication  
javax.naming.CommunicationException [Root exception is java.io.IOException: connection closed]; remaining name ''  
        at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:157)  
        at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2685)  
        at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2593)  
        at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2567)  
        at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1932)  
        at com.sun.jndi.ldap.LdapCtx.doSearchOnce(LdapCtx.java:1924)  
        at com.sun.jndi.ldap.LdapCtx.c_getAttributes(LdapCtx.java:1317)  
        at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_getAttributes(ComponentDirContext.java:231)  
        at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:139)  
        at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:127)  
        at javax.naming.directory.InitialDirContext.getAttributes(InitialDirContext.java:140)  
        at org.apache.catalina.realm.JNDIRealm.bindAsUser(JNDIRealm.java:1621)  
        at org.apache.catalina.realm.JNDIRealm.checkCredentials(JNDIRealm.java:1480)  
        at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:1131)  
        at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:1016)  
        at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:282)  
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:440)  
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)  
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)  
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)  
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)  
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)  
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)  
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)  
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)  
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)  
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)  
        at java.lang.Thread.run(Thread.java:636)  
Caused by: java.io.IOException: connection closed  
        at com.sun.jndi.ldap.LdapClient.ensureOpen(LdapClient.java:1576)  
        at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:155)  
        ... 27 more  
Run Code Online (Sandbox Code Playgroud)

LDAP配置位于应用程序的context.xml文件中:

<Realm className="org.apache.catalina.realm.JNDIRealm"  
    connectionURL="ldaps://ldap-company.com"  
    userPattern="uid={0},dc=company,dc=com"  
    roleBase="ou=groups,o=company"  
    roleName="uid"  
    roleSearch="uniqueMember={0}"  
    roleSubtree="true" />  
Run Code Online (Sandbox Code Playgroud)

我从几个论坛找到了关于这个问题的帖子,但似乎没有人想出解决方案.

Din*_*son 6

我能够找出警告的原因,并找到摆脱它的方法.

发出警告的原因是LDAP服务器正在关闭所有空闲超过5分钟的连接.LDAP服务器管理员告诉我,建议在每次登录请求后立即关闭连接,因为可用句柄的数量是有限的.但是,Tomcat的JNDIRealm没有提供配置方法,所以我通过扩展JNDIRealm类并覆盖authenticate(..)方法解决了这个问题.所有需要做的就是在每次身份验证请求和警告消失后关闭与LDAP服务器的连接.

请注意,包需要与JNDIRealm类相同,否则无法访问上下文变量.

package org.apache.catalina.realm;

import java.security.Principal;

public class CustomJNDIRealm extends JNDIRealm {
  @Override
  public Principal authenticate(String username, String credentials) {
  Principal principal = super.authenticate(username, credentials);

    if (context != null) {
      close(context);
    }
    return principal;
  }
}
Run Code Online (Sandbox Code Playgroud)

生成的jar需要放在Tomcat的lib文件夹下,并将应用程序的context.xml中的className更改为org.apache.catalina.realm.CustomJNDIRealm.然后重新启动Tomcat就是这样.

<Realm className="org.apache.catalina.realm.CustomJNDIRealm"  
  connectionURL="ldaps://ldap-company.com"  
  userPattern="uid={0},dc=company,dc=com"  
  roleBase="ou=groups,o=company"  
  roleName="uid"  
  roleSearch="uniqueMember={0}"  
  roleSubtree="true" /> 
Run Code Online (Sandbox Code Playgroud)


Ter*_*ner 1

LDAP 服务器正在断开一段时间后处于空闲状态(即没有发送任何请求)的空闲连接。