2009-07-16 15 views
9

LDAPサーバーが認証にのみ使用され、ロールは含まれておらず、ユーザーロールマッピングを含むデータベースに対して承認が行われるレガシー環境では、パスワードはありません。LDAP認証とJDBC認証を使用してTomcatレルムを実装する

私の計画は、JNDIRealmを拡張し、カプセル化されたJDBCRealmを呼び出すロールメソッドをオーバーライドすることで、新しいTomcat Realmを実装することです。

私のレルムはserver.xmlで宣言されている:彼らは両方のconnectionURLを使用するよう

<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" /> 

は、これはほとんど変化して、JNDIレルム& JDBCレルムのための標準的なプロパティ名を組み合わせたものです。

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、より主体を返します。同じプリンシパルがhasResourcePermission()と入力され、それに必要な役割がないために失敗します。明らかに私はいくつかの重要なコードが欠けている。

私は解決策を探しています。私はJDBCRealmを拡張しLDAP認証を追加しようとする可能性がありますが、それはもっとうまくいくようです。

私はこのLDAP認証/ DB認証が珍しいパターンではないとも考えています。既に利用可能な代替ソリューションがありますか?

それはDBにLDAPやパスワードに役割を追加するために私のコントロール内ではないので、それらは私のためのソリューションではありません。

+0

はい、私は、JDBCレルムかかわら呼び出すためのTomcat 6.0.18 –

答えて

5

使用しているTomcatのバージョンを指定していないため、ここで6.xを使用します。

hasResourcePermissionをJDBCに委任しているようですが、findSecurityConstraintshasUserDataPermissionの両方をJNDIの手元に置いているようです。それらのすべてを委譲するか、いずれも委任しないでください。

更新:そのauthenticate()方法の一部としてprotected getRoles(DirContext, User)を呼び出しJNDIRealm。これをオーバーライドしてJDBCRealmのgetRoles()に転送する必要があります。

+0

私はfindSecurityConstraintsをオーバーライドしてきました()&hasUserDataPermission()で働いています。ただし、JDBCRealmのgetRoles()は保護されています。私はそれをどのように提案するのですか? –

+1

あなたは3つの選択肢があります:リフレクション( 'Method.setAccessible()'は 'protected'の助けになります)を使用し、realmの実装を' org.apache.catalina.realm'パッケージに移動するか、JDBCRealmを一切忘れて、データベースからロールを取得します)。 – ChssPly76

+0

org.apache.catalina.realmパッケージへの移行は非常にうまくいった。私もドライバーを指定することを怠っていたので、DBユーザーとパスワードだけでなくgetterとsetterも追加しました。すべてがうまくいきます、ありがとう。 –

13

私はまだこの質問に関する電子メールを定期的な頻度で受け取っていますので、ここではすべての製品を使用するための最終製品です。


LdapJdbcRealm.java

package org.apache.catalina.realm; 

import org.apache.catalina.Realm; 
import org.apache.catalina.Context; 
import org.apache.catalina.connector.Request; 
import org.apache.catalina.connector.Response; 
import org.apache.catalina.deploy.SecurityConstraint; 

import javax.naming.directory.DirContext; 
import java.io.IOException; 
import java.security.Principal; 
import java.util.List; 

/** 
* LdapJdbcRealm is a minimal implementation of a <b>Realm</b> to connect to LDAP 
* for authentication and a database for authorization.<br> 
* <br> 
* Example server.xml configuration fragment:<br> 
* <pre> 
    &lt;Realm className="org.apache.catalina.realm.LdapJdbcRealm" 
     connectionURL="ldap://ldaphost:389" 
     resourceName="LDAP Auth" driverName="oracle.jdbc.driver.OracleDriver" 
     userPattern="uid={0}, ou=Portal, dc=example, dc=com" 
     dbConnectionName="dbuser" dbConnectionPassword="dbpassword" 
     dbConnectionURL="jdbc:oracle:thin:@oracledb:1521:dbname" 
     userTable="users" userNameCol="user_id" 
     userRoleTable="user_role_xref" roleNameCol="role_id" /&gt; 
* </pre> 
* 
* @author Greg Chabala 
* 
* Created by IntelliJ IDEA. 
* User: gchabala 
* Date: Jul 14, 2009 
* Time: 4:56:37 PM 
*/ 
public class LdapJdbcRealm extends JNDIRealm implements Realm 
{ 
    /** 
    * Encapsulated <b>JDBCRealm</b> to do role lookups 
    */ 
    private JDBCRealm jdbcRealm = new JDBCRealm(); 

    /** 
    * Descriptive information about this <b>Realm</b> implementation. 
    */ 
    protected static final String info = "org.apache.catalina.realm.LdapJdbcRealm/1.0"; 

    /** 
    * Descriptive information about this <b>Realm</b> implementation. 
    */ 
    protected static final String name = "LdapJdbcRealm"; 

    /** 
    * Set the all roles mode. 
    * 
    * @param allRolesMode authentication mode 
    */ 
    public void setAllRolesMode(String allRolesMode) { 
     super.setAllRolesMode(allRolesMode); 
     jdbcRealm.setAllRolesMode(allRolesMode); 
    } 

    /** 
    * Return the username to use to connect to the database. 
    * 
    * @return username 
    * @see JDBCRealm#getConnectionName() 
    */ 
    public String getDbConnectionName() { 
     return jdbcRealm.getConnectionName(); 
    } 

    /** 
    * Set the username to use to connect to the database. 
    * 
    * @param dbConnectionName username 
    * @see JDBCRealm#setConnectionName(String) 
    */ 
    public void setDbConnectionName(String dbConnectionName) { 
     jdbcRealm.setConnectionName(dbConnectionName); 
    } 

    /** 
    * Return the password to use to connect to the database. 
    * 
    * @return password 
    * @see JDBCRealm#getConnectionPassword() 
    */ 
    public String getDbConnectionPassword() { 
     return jdbcRealm.getConnectionPassword(); 
    } 

    /** 
    * Set the password to use to connect to the database. 
    * 
    * @param dbConnectionPassword password 
    * @see JDBCRealm#setConnectionPassword(String) 
    */ 
    public void setDbConnectionPassword(String dbConnectionPassword) { 
     jdbcRealm.setConnectionPassword(dbConnectionPassword); 
    } 

    /** 
    * Return the URL to use to connect to the database. 
    * 
    * @return database connection URL 
    * @see JDBCRealm#getConnectionURL() 
    */ 
    public String getDbConnectionURL() { 
     return jdbcRealm.getConnectionURL(); 
    } 

    /** 
    * Set the URL to use to connect to the database. 
    * 
    * @param dbConnectionURL The new connection URL 
    * @see JDBCRealm#setConnectionURL(String) 
    */ 
    public void setDbConnectionURL(String dbConnectionURL) { 
     jdbcRealm.setConnectionURL(dbConnectionURL); 
    } 

    /** 
    * Return the JDBC driver that will be used. 
    * 
    * @return driver classname 
    * @see JDBCRealm#getDriverName() 
    */ 
    public String getDriverName() { 
     return jdbcRealm.getDriverName(); 
    } 

    /** 
    * Set the JDBC driver that will be used. 
    * 
    * @param driverName The driver name 
    * @see JDBCRealm#setDriverName(String) 
    */ 
    public void setDriverName(String driverName) { 
     jdbcRealm.setDriverName(driverName); 
    } 

    /** 
    * Return the table that holds user data.. 
    * 
    * @return table name 
    * @see JDBCRealm#getUserTable() 
    */ 
    public String getUserTable() { 
     return jdbcRealm.getUserTable(); 
    } 

    /** 
    * Set the table that holds user data. 
    * 
    * @param userTable The table name 
    * @see JDBCRealm#setUserTable(String) 
    */ 
    public void setUserTable(String userTable) { 
     jdbcRealm.setUserTable(userTable); 
    } 

    /** 
    * Return the column in the user table that holds the user's name. 
    * 
    * @return username database column name 
    * @see JDBCRealm#getUserNameCol() 
    */ 
    public String getUserNameCol() { 
     return jdbcRealm.getUserNameCol(); 
    } 

    /** 
    * Set the column in the user table that holds the user's name. 
    * 
    * @param userNameCol The column name 
    * @see JDBCRealm#setUserNameCol(String) 
    */ 
    public void setUserNameCol(String userNameCol) { 
     jdbcRealm.setUserNameCol(userNameCol); 
    } 

    /** 
    * Return the table that holds the relation between user's and roles. 
    * 
    * @return user role database table name 
    * @see JDBCRealm#getUserRoleTable() 
    */ 
    public String getUserRoleTable() { 
     return jdbcRealm.getUserRoleTable(); 
    } 

    /** 
    * Set the table that holds the relation between user's and roles. 
    * 
    * @param userRoleTable The table name 
    * @see JDBCRealm#setUserRoleTable(String) 
    */ 
    public void setUserRoleTable(String userRoleTable) { 
     jdbcRealm.setUserRoleTable(userRoleTable); 
    } 

    /** 
    * Return the column in the user role table that names a role. 
    * 
    * @return role column name 
    * @see JDBCRealm#getRoleNameCol() 
    */ 
    public String getRoleNameCol() { 
     return jdbcRealm.getRoleNameCol(); 
    } 

    /** 
    * Set the column in the user role table that names a role. 
    * 
    * @param roleNameCol The column name 
    * @see JDBCRealm#setRoleNameCol(String) 
    */ 
    public void setRoleNameCol(String roleNameCol) { 
     jdbcRealm.setRoleNameCol(roleNameCol); 
    } 

    @Override 
    public SecurityConstraint[] findSecurityConstraints(Request request, Context context) 
    { 
     return jdbcRealm.findSecurityConstraints(request, context); 
    } 

    @Override 
    public boolean hasUserDataPermission(Request request, Response response, 
             SecurityConstraint []constraints) throws IOException 
    { 
     return jdbcRealm.hasUserDataPermission(request, response, constraints); 
    } 

    @Override 
    public boolean hasResourcePermission(Request request, Response response, 
             SecurityConstraint[]constraints, 
             Context context) throws IOException 
    { 
     return jdbcRealm.hasResourcePermission(request, response, constraints, context); 
    } 

    @Override 
    public boolean hasRole(Principal principal, String role) { 
     return jdbcRealm.hasRole(principal, role); 
    } 

    /** 
    * Return a List of roles associated with the given User. If no roles 
    * are associated with this user, a zero-length List is returned. 
    * 
    * @param context unused. JDBC does not need this field. 
    * @param user The User to be checked 
    * @return list of role names 
    * 
    * @see JNDIRealm#getRoles(DirContext, User) 
    * @see JDBCRealm#getRoles(String) 
    */ 
    @Override 
    protected List<String> getRoles(DirContext context, User user) 
    { 
     return jdbcRealm.getRoles(user.username); 
    } 
} 
+0

こんにちは、私はこれをgithubに載せています:https://github.com/rasenderhase/nest-tomcat-realms/私はプルリクエストに満足しています。 – andy