You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tomcat自定义JNDIRealm中如何获取Request对象以对接不同LDAP服务器

自定义JNDIRealm获取Request对象及按请求来源切换LDAP服务器实现方案

以下为Tomcat环境下的标准实现方案:

推荐实现方式(适配Tomcat 8.0及以上版本)

Tomcat 8.0+版本的JNDIRealm父类RealmBase已经提供了带Request参数的authenticate重载方法,直接重写该方法即可原生获取Request对象,无需额外适配:

import org.apache.catalina.connector.Request;
import org.apache.catalina.realm.JNDIRealm;
import javax.servlet.http.HttpServletResponse;
import java.security.Principal;

public class CustomRouteLdapRealm extends JNDIRealm {
    // 内网普通LDAP服务器地址
    private String innerLdapUrl;
    // 外网双因子LDAP服务器地址
    private String outerLdapUrl;

    @Override
    public Principal authenticate(Request request, HttpServletResponse response) {
        // 直接从Request对象获取客户端IP判断网络来源
        String clientIp = request.getRemoteAddr();
        boolean isInnerAccess = checkInnerNetwork(clientIp);

        // 高并发场景建议不要直接修改全局connectionURL成员变量,避免线程安全问题
        // 推荐重写getDirectoryContext()方法,根据当前网络标识动态创建对应LDAP的上下文
        if (isInnerAccess) {
            setConnectionURL(innerLdapUrl);
        } else {
            setConnectionURL(outerLdapUrl);
        }

        // 复用父类原有JNDI认证逻辑
        return super.authenticate(request, response);
    }

    /**
     * 自定义内网IP判断逻辑,可根据实际网段调整
     */
    private boolean checkInnerNetwork(String clientIp) {
        return clientIp.startsWith("10.")
                || clientIp.startsWith("192.168.")
                || clientIp.matches("172\\.(1[6-9]|2[0-9]|3[01])\\..*");
    }

    // 配置参数注入方法,供server.xml配置调用
    public void setInnerLdapUrl(String innerLdapUrl) {
        this.innerLdapUrl = innerLdapUrl;
    }

    public void setOuterLdapUrl(String outerLdapUrl) {
        this.outerLdapUrl = outerLdapUrl;
    }
}

低版本Tomcat兼容方案(适配Tomcat 7及以下版本)

如果使用的Tomcat版本没有带Request参数的authenticate重载方法,可通过自定义Valve传递Request:

  • 实现自定义Valve,在invoke方法中将当前Request存入ThreadLocal<Request>
  • 在自定义JNDIRealm的认证逻辑中从ThreadLocal取出Request对象
  • 请求处理完成后必须手动清除ThreadLocal,避免内存泄漏

部署配置

将编译好的自定义Realm的jar包放入Tomcatlib/目录,修改server.xml中的Realm配置即可:

<Realm className="com.yourpackage.CustomRouteLdapRealm"
       innerLdapUrl="ldap://内网LDAP地址:389"
       outerLdapUrl="ldap://外网双因子LDAP地址:389"
       <!-- 保留原有JNDIRealm的其他配置项,如connectionName、userSearch、userPattern等 -->
/>

注意:高并发场景下直接修改connectionURL成员变量存在线程安全问题,建议重写getDirectoryContext()方法,根据当前请求的网络属性动态创建对应LDAP服务器的上下文,不要修改全局配置变量。

内容的提问来源于stack exchange,提问作者zackhalil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 00:15:02