Liberty LDAP security-role与group映射失效问题排查求助
结合你的配置、自定义登录模块代码以及日志信息,我来一步步拆解这个授权失败的问题,帮你定位根因并给出解决方向:
一、组ID的正确格式:必须匹配授权逻辑的期望格式
你现在的核心疑问是「添加组字符串还是DN」,答案是取决于你application-bnd中的配置格式,以及Liberty授权时的匹配规则:
Liberty的授权逻辑是将Subject中WSCredential的groupIds内容,与application-bnd里配置的组标识做精确匹配,而匹配的关键是格式要统一:
- 如果你的
application-bnd用的是短组名:<group name="App.Admin"/>
那你需要确认LDAP注册表配置的groupNameAttribute(比如cn)是否对应这个短名称,此时groupIds中需要添加完全一致的短组名字符串,或者添加组的access-id格式(group:LdapRegistry/cn=App.Admin,ou=ent,ou=App,ou=apps,o=somedir)。 - 如果你的
application-bnd用的是完整DN:<group name="cn=App.Admin,ou=ent,ou=App,ou=apps,o=somedir"/>
那groupIds中必须添加完全一致的DN字符串,或者对应的access-id格式。
从你的trace日志App.Admin=[]可以看出:授权表中角色MyAdmin对应的组App.Admin没有关联到任何用户,说明你添加到groupIds的内容和配置的组标识不匹配。
二、自定义登录模块的正确写法:添加组的Access-ID
你当前直接添加组名/DN到groupIds的方式可能不符合Liberty授权的期望,正确的做法是添加组的access-id格式字符串,格式为:group:<RealmName>/<GroupDN>。
修改你的自定义登录模块代码如下:
WSCredential credential = (WSCredential) _sharedState.get(com.ibm.wsspi.security.auth.callback.Constants.WSCREDENTIAL_KEY); String[] grpList = ldapEntry.getAttribute("myEntGrps").getValues(); for (int i = 0; i < grpList.length; i++) { // 拼接组的access-id格式 String groupAccessId = "group:LdapRegistry/" + grpList[i]; credential.getGroupIds().add(groupAccessId); }
同时,把application-bnd中的组配置改成access-id格式,确保完全匹配:
<security-role name="MyAdmin"> <group access-id="group:LdapRegistry/cn=App.Admin,ou=ent,ou=App,ou=apps,o=somedir"/> </security-role>
三、排查测试方法:验证每一步的正确性
- 打印Subject的详细信息:在受保护的Servlet中添加代码,输出
Subject里的groupIds内容,确认自定义登录模块是否成功添加了正确的组标识:Subject subject = com.ibm.websphere.security.auth.WSSubject.getCallerSubject(); WSCredential cred = (WSCredential) subject.getPublicCredentials(WSCredential.class).iterator().next(); System.out.println("Group IDs in credential: " + cred.getGroupIds()); - 启用更精细的trace日志:在现有trace基础上添加
com.ibm.ws.security.authorization.*=all,这样能看到授权时的具体匹配过程——比如Liberty会把Subject中的每个groupIds和角色映射的组逐一比较,日志会告诉你哪一步不匹配。 - 测试单组映射:先只配置一个组到角色
MyAdmin,简化场景,确认匹配逻辑生效后再添加其他组。
四、组映射的后台处理逻辑
Liberty的授权流程大致是这样的:
- 部署阶段:解析
application-bnd中的角色映射,将每个角色对应的用户/组(名称或access-id)存入授权映射表; - 请求阶段:用户登录后,从
Subject中提取用户的access-id和WSCredential里的groupIds; - 匹配阶段:将用户的access-id、所有groupIds与授权映射表中的角色条目逐一匹配,只要有一个匹配成功就授权通过,否则返回
CWWKS9104A错误。
你的trace日志updateMapsForAccessId Exit {user:LdapRegistry/uid=MEMYSELFANDI,ou=person,o=somedir=[],App.Admin=[]}说明:授权表中,用户的access-id没有关联到MyAdmin,组App.Admin也没有关联到MyAdmin——这进一步证实了组标识的格式不匹配。
五、日志配置优化
除了你当前的trace配置,建议添加以下日志项来获取更关键的信息:
traceSpecification="*=info:com.ibm.ws.security.*=all:com.ibm.websphere.security.*=all:com.ibm.ws.webcontainer.security.*=all:com.ibm.ws.wim.*=all:com.ibm.ws.security.authorization.*=all:com.ibm.ws.security.credentials.*=all:com.ibm.ws.security.auth.login.*=all"/>
com.ibm.ws.security.authorization.*=all:跟踪授权匹配的每一步细节;com.ibm.ws.security.credentials.*=all:监控WSCredential的修改和组ID的存储情况;com.ibm.ws.security.auth.login.*=all:查看自定义登录模块的执行过程,确认组列表是否正确获取。
内容的提问来源于stack exchange,提问作者kinglite

