一尘不染

使用LDAP身份验证和JDBC授权实现Tomcat Realm

tomcat

我在旧环境中工作,在该环境中,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()并失败,因为它没有必需的角色。显然,我缺少一些关键代码。

我正在寻找解决方案。我可以尝试扩展JDBCRealm并添加LDAP身份验证,但这似乎需要更多工作。

我还相信,这种LDAP身份验证/数据库授权不是常见的模式。是否已有替代解决方案?

这是 不是 我的控制范围之内将角色添加到LDAP或密码的数据库,所以这些都是不适合我的解决方案。


阅读 486

收藏
2020-06-16

共1个答案

一尘不染

您尚未指定要使用的Tomcat版本,所以我在这里使用6.x。

它看起来像你委托hasResourcePermission给JDBC同时使双方findSecurityConstraintshasUserDataPermission在JNDI的手中。您应该委派所有人员,也可以不委派任何人。

更新 :作为其方法的一部分进行JNDIRealm调用。您需要重写它并将其转发到JDBCRealm的。protected getRoles(DirContext, User)``authenticate()``getRoles()

2020-06-16