WAS9部署两个带ESAPI2.1的Web应用出现验证配置类型未设置错误
ESAPI多应用部署配置冲突解决方案
问题根因
- ESAPI 2.1版本核心组件默认采用静态单例模式实现,类加载后只会初始化一次配置,不会区分不同Web应用上下文
- WebSphere Application Server 9默认类加载策略为父类加载器优先,如果两个应用都将ESAPI依赖包放在WEB-INF/lib目录下,先部署的应用A的ESAPI类会被父类加载器加载,后部署的应用B会复用已加载的ESAPI类,直接读取应用A的配置,不会重新加载自身的配置文件
解决方案步骤
第一步:调整WAS应用类加载策略
优先通过类加载隔离解决共享类问题,每个应用单独配置加载规则:
- 进入WAS管理控制台,依次进入应用程序 > 应用程序类型 > WebSphere 企业应用程序,分别选中应用A、应用B
- 点击「类加载和更新检测」,选择如下配置:
- 类加载顺序:先加载本地类加载器的类(父类加载器最后)
- WAR类加载器策略:为每个WAR文件使用单独的类加载器
- 保存配置后重启对应应用,或直接重启WAS节点生效
第二步:强制指定应用ESAPI配置(类加载调整后仍不生效时补充)
你之前配置的web.xml上下文参数在ESAPI单例已初始化的场景下不会触发重新加载,可在应用B的初始化入口强制指定当前应用的配置路径:
- 新增ServletContextListener,在应用启动时优先加载本应用的ESAPI配置,代码示例:
import org.owasp.esapi.ESAPI; import org.owasp.esapi.reference.DefaultSecurityConfiguration; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import java.io.FileInputStream; import java.io.InputStream; public class EsapiInitListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { try { // 指定当前应用WEB-INF下的ESAPI配置路径 String esapiPath = sce.getServletContext().getRealPath("/WEB-INF/esapi/ESAPI.properties"); String validationPath = sce.getServletContext().getRealPath("/WEB-INF/esapi/validation.properties"); // 强制重置ESAPI配置 DefaultSecurityConfiguration config = new DefaultSecurityConfiguration(); try(InputStream esapiIn = new FileInputStream(esapiPath); InputStream validationIn = new FileInputStream(validationPath)) { config.loadPropertiesFromStream(esapiIn); config.loadPropertiesFromStream(validationIn); ESAPI.override(config); } } catch (Exception e) { throw new RuntimeException("应用B ESAPI配置初始化失败", e); } } @Override public void contextDestroyed(ServletContextEvent sce) { // 无需额外处理 } }
- 在应用B的web.xml中注册该监听器,注意要放在所有其他监听器的最前面,保证优先执行:
<listener> <listener-class>替换为你自己的包路径.EsapiInitListener</listener-class> </listener>
第三步:配置验证
调整完成后清空WAS临时目录,重启两个应用,先验证应用A的原有校验规则正常,再验证应用B的自定义校验规则可正常调用,无配置不存在的报错即可。
内容的提问来源于stack exchange,提问作者enK
相关产品推荐
相关产品推荐

