我在旧环境中工作,在该环境中,LDAP服务器仅用于身份验证,不包含任何角色,并且对包含用户角色映射但不包含密码的数据库进行授权。
我的计划是通过扩展JNDIRealm并重写角色方法以调用封装的JDBCRealm来实现新的Tomcat Realm。
我的领域在server.xml中声明:
<Realm className="com.example.LdapJdbcRealm" connectionURL="ldap://ldaphost:389" resourceName="LDAP Auth" userPattern="uid={0}, ou=Portal, dc=example, dc=com" dbConnectionURL="jdbc:oracle:thin:@oracledb:1521:dbname" userTable="db_user" userNameCol="user_id" userRoleTable="db_user_role_xref" roleNameCol="role_id" />
这是JNDIRealm和JDBCRealm的标准属性名称的组合,只有一点点更改,因为它们都使用connectionURL。
package com.example; import org.apache.catalina.Realm; import org.apache.catalina.Context; import org.apache.catalina.deploy.SecurityConstraint; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.realm.JNDIRealm; import org.apache.catalina.realm.JDBCRealm; import java.security.Principal; import java.io.IOException; public class LdapJdbcRealm extends JNDIRealm implements Realm { private JDBCRealm jdbcRealm = new JDBCRealm(); protected static final String info = "com.example.LdapJdbcRealm/1.0"; protected static final String name = "LdapJdbcRealm"; public String getDbConnectionURL() { return jdbcRealm.getConnectionURL(); } public void setDbConnectionURL(String dbConnectionURL) { jdbcRealm.setConnectionURL(dbConnectionURL); } public String getUserTable() { return jdbcRealm.getUserTable(); } public void setUserTable(String userTable) { jdbcRealm.setUserTable(userTable); } public String getUserNameCol() { return jdbcRealm.getUserNameCol(); } public void setUserNameCol(String userNameCol) { jdbcRealm.setUserNameCol(userNameCol); } public String getUserRoleTable() { return jdbcRealm.getUserRoleTable(); } public void setUserRoleTable(String userRoleTable) { jdbcRealm.setUserRoleTable(userRoleTable); } public String getRoleNameCol() { return jdbcRealm.getRoleNameCol(); } public void setRoleNameCol(String roleNameCol) { jdbcRealm.setRoleNameCol(roleNameCol); } public boolean hasResourcePermission(Request request, Response response, SecurityConstraint[]constraints, Context context) throws IOException { return jdbcRealm.hasResourcePermission(request, response, constraints, context); } public boolean hasRole(Principal principal, String role) { return jdbcRealm.hasRole(principal, role); } }
这似乎大部分可行,授权从LDAP返回一个主体,该主体没有预期的作用。相同的Principal进入hasResourcePermission()并失败,因为它没有必需的角色。显然,我缺少一些关键代码。
hasResourcePermission()
我正在寻找解决方案。我可以尝试扩展JDBCRealm并添加LDAP身份验证,但这似乎需要更多工作。
我还相信,这种LDAP身份验证/数据库授权不是常见的模式。是否已有替代解决方案?
这是 不是 我的控制范围之内将角色添加到LDAP或密码的数据库,所以这些都是不适合我的解决方案。
您尚未指定要使用的Tomcat版本,所以我在这里使用6.x。
它看起来像你委托hasResourcePermission给JDBC同时使双方findSecurityConstraints和hasUserDataPermission在JNDI的手中。您应该委派所有人员,也可以不委派任何人。
hasResourcePermission
findSecurityConstraints
hasUserDataPermission
更新 :作为其方法的一部分进行JNDIRealm调用。您需要重写它并将其转发到JDBCRealm的。protected getRoles(DirContext, User)``authenticate()``getRoles()
JNDIRealm
protected getRoles(DirContext, User)``authenticate()``getRoles()