迁移至Open Liberty后自定义LoginModule出现ClassNotFoundException
自定义LoginModule在Open Liberty中加载失败的问题排查与解决
环境信息
- Open Liberty版本:24.0.0.6
- JDK:RedHat OpenJDK 17
- Jakarta EE:10
操作步骤
- 创建
jaas.config文件,内容如下:
case1 { com.sample.security.CustomLoginModule required; };
- 在
{server_name}/jvmoptions中配置JAAS配置文件路径:
-Djava.security.auth.login.config=/opt/liberty/config/jaas.config
- 部署应用并启动Open Liberty(未在
server.xml中配置特定JAAS规则,预期自动读取jaas.config)
遇到的问题
- 应用启动时抛出
ClassNotFoundException,提示无法加载自定义LoginModule,日志片段:
[2024/10/17 8:00:38:814 UTC] 00000018 m.ws.security.jaas.common.internal.JAASLoginModuleConfigImpl E CWWKS1141E: An unexpected exception occurred while executing class for name: com.sample.security.CustomLoginModule. Exception: java.lang.ClassNotFoundException: com.sample.security.CustomLoginModule at com.ibm.ws.classloading.internal.AppClassLoader.findClassCommonLibraryClassLoaders(AppClassLoader.java:751) at com.ibm.ws.classloading.internal.AppClassLoader.findClass(AppClassLoader.java:327) at com.ibm.ws.classloading.internal.AppClassLoader.findOrDelegateLoadClass(AppClassLoader.java:705) at com.ibm.ws.classloading.internal.AppClassLoader.loadClass(AppClassLoader.java:584) at com.ibm.ws.classloading.internal.AppClassLoader.loadClass(AppClassLoader.java:553) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:467) at com.ibm.ws.security.jaas.common.internal.JAASLoginModuleConfigImpl.processDelegateOptions(JAASLoginModuleConfigImpl.java:251) at com.ibm.ws.security.jaas.config.internal.JAASLoginConfigImpl.updateAppConfiguration(JAASLoginConfigImpl.java:194) at com.ibm.ws.security.jaas.config.internal.JAASLoginConfigImpl.updateDelegateOptions(JAASLoginConfigImpl.java:173) at com.ibm.ws.security.jaas.config.internal.JAASLoginConfigImpl.getEntries(JAASLoginConfigImpl.java:150) at com.ibm.ws.security.jaas.common.JAASConfigurationFactory.installJAASConfigurationFromJAASConfigFile(JAASConfigurationFactory.java:123) at com.ibm.ws.security.jaas.common.JAASConfigurationFactory.activate(JAASConfigurationFactory.java:86)
- 运行测试用例时,日志提示缺少
delegate选项
问题分析
1. 类加载路径问题
Open Liberty读取外部jaas.config时,使用的是服务器类加载器,而你的自定义LoginModule打包在应用EAR中,属于应用类加载器的范围,服务器类加载器无法访问应用内部的类——这是和WebSphere/JBoss的核心差异之一,后两者在读取JAAS配置时会自动委托应用类加载器,而Open Liberty需要显式配置。
2. 缺少委托配置
日志中提到的“缺少delegate选项”,是因为Open Liberty需要通过代理模块来桥接服务器类加载器和应用类加载器,你需要指定委托的目标LoginModule类名。
解决方案
方案一:将LoginModule部署到服务器共享库(快速临时方案)
- 在服务器目录下创建
{server_name}/lib/global目录(如果不存在) - 将包含
com.sample.security.CustomLoginModule的JAR文件复制到该目录 - 重启Open Liberty,服务器类加载器会自动加载这个目录下的类,即可解决
ClassNotFoundException
方案二:使用Open Liberty JAAS代理配置(推荐,无需移动类)
移除JVM参数-Djava.security.auth.login.config,在server.xml中添加以下JAAS配置,通过Open Liberty提供的代理模块委托应用类加载器加载自定义LoginModule:
<jaasLoginContextEntry id="case1" name="case1"> <jaasLoginModule className="com.ibm.ws.security.jaas.common.server.WSLoginModuleProxy" controlFlag="REQUIRED"> <properties delegate="com.sample.security.CustomLoginModule" delegateClassName="com.sample.security.CustomLoginModule" classLoaderRef="application" /> </jaasLoginModule> </jaasLoginContextEntry>
WSLoginModuleProxy:Open Liberty官方提供的代理类,负责将登录请求转发给应用中的自定义LoginModuleclassLoaderRef="application":指定使用应用类加载器加载委托的类,确保能找到EAR中的CustomLoginModuledelegate/delegateClassName:明确指定需要委托的自定义LoginModule全类名,解决“缺少delegate选项”的问题
配置完成后重启服务器,即可正常加载自定义LoginModule。
内容的提问来源于stack exchange,提问作者金田一太郎
相关产品推荐
相关产品推荐

