使用LDAP身份验证和JDBC授权实现Tomcat领域
我在一个遗留环境中工作,其中LDAP服务器仅用于身份验证,不包含任何角色,授权是针对包含用户角色映射但不包含密码的数据库进行的 我的计划是通过扩展JNDIRealm实现一个新的Tomcat领域,并重写role方法来调用封装的JDBCRealm 我的领域在server.xml中声明:使用LDAP身份验证和JDBC授权实现Tomcat领域,tomcat,jdbc,ldap,authorization,Tomcat,Jdbc,Ldap,Authorization,我在一个遗留环境中工作,其中LDAP服务器仅用于身份验证,不包含任何角色,授权是针对包含用户角色映射但不包含密码的数据库进行的 我的计划是通过扩展JNDIRealm实现一个新的Tomcat领域,并重写role方法来调用封装的JDBCRealm 我的领域在server.xml中声明: <Realm className="com.example.LdapJdbcRealm" connectionURL="ldap://ldaphost:389" resourceName="LDAP
<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" />
这似乎大部分是可行的,授权从LDAP返回一个主体,LDAP没有预期的角色。同一主体进入hasrourcepermission()
并失败,因为其中没有require角色。很明显,我遗漏了一些关键代码
我在寻找解决办法。我可以尝试扩展JDBCRealm并添加LDAP身份验证,但这似乎需要更多的工作
我还认为,这种LDAP身份验证/DB授权模式并不少见。是否已有替代解决方案
将角色添加到LDAP或将密码添加到DB不在我的控制范围之内,因此这些都不是我的解决方案。您尚未指定您使用的Tomcat版本,因此我在这里使用6.x 看起来您正在将
hasResourcePermission
委托给JDBC,同时将findSecurityConstraints
和hasUserDataPermission
都交给JNDI。你应该把他们全部委派,或者一个也不委派
更新:
jndiream
调用受保护的getRoles(DirContext,User)
作为其authenticate()方法的一部分。您需要覆盖它并将其转发给JDBCRealm的getRoles()
我仍然经常收到关于这个问题的电子邮件,因此这里是供所有人使用的最终产品
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>
<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" />
* </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);
}
}
package org.apache.catalina.realm;
导入org.apache.catalina.Realm;
导入org.apache.catalina.Context;
导入org.apache.catalina.connector.Request;
导入org.apache.catalina.connector.Response;
导入org.apache.catalina.deploy.SecurityConstraint;
导入javax.naming.directory.DirContext;
导入java.io.IOException;
导入java.security.Principal;
导入java.util.List;
/**
*LdapJdbcRealm是连接到LDAP的领域的最小实现
*用于身份验证和数据库用于授权。
*
*示例server.xml配置片段:
*
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\u id”
userRoleTable=“用户角色外部参照”roleNameCol=“角色id”/
*
*
*@作者Greg Chabala
*
*由IntelliJ IDEA创建。
*用户:gchabala
*日期:2009年7月14日
*时间:下午4:56:37
*/
公共类LdapJdbcRealm扩展JNDIRealm实现领域
{
/**
*封装JDBCRealm以进行角色查找
*/
私有jdbcream jdbcream=新jdbcream();
/**
*有关此领域实现的描述性信息。
*/
受保护的静态最终字符串info=“org.apache.catalina.realm.LdapJdbcRealm/1.0”;
/**
*有关此领域实现的描述性信息。
*/
受保护的静态最终字符串名称=“LdapJdbcRealm”;
/**
*设置所有角色模式。
*
*@param AllRoleMode身份验证模式
*/
public void setAllRoleMode(字符串AllRoleMode){
super.setAllRoleMode(AllRoleMode);
setAllRoleMode(AllRoleMode);
}
/**
*返回用于连接数据库的用户名。
*
*@return用户名
*@see JDBCRealm#getConnectionName()
*/
公共字符串getDbConnectionName(){
返回jdbcRealm.getConnectionName();
}
/**
*设置用于连接数据库的用户名。
*
*@param dbConnectionName用户名
*@see JDBCRealm#setConnectionName(字符串)
*/
public void setDbConnectionName(字符串dbConnectionName){
setConnectionName(dbConnectionName);
}
/**
*返回用于连接数据库的密码。
*
*@返回密码
*@see JDBCRealm#getConnectionPassword()
*/
公共字符串getDbConnectionPassword(){
返回jdbcRealm.getConnectionPassword();
}
/**
*设置用于连接数据库的密码。
*
*@param dbConnectionPassword
*@see JDBCRealm#setConnectionPassword(字符串)
*/
public void setDbConnectionPassword(字符串dbConnectionPassword){
setConnectionPassword(dbConnectionPassword);
}
/**
*返回用于连接数据库的URL。
*
*@return数据库连接URL
*@see JDBCRealm#getConnectionURL()
*/
公共字符串getDbConnectionURL(){
返回jdbcRealm.getConnectionURL();
}
/**
*设置用于连接数据库的URL。
*
*@param dbConnectionURL新的连接URL
*@see JDBCRealm#setConnectionURL(字符串)
*/
public void setDbConnectionURL(字符串dbConnectionURL){
setConnectionURL(dbConnectionURL);
}
/**
*返回将要使用的JDBC驱动程序。
*
*@return-driver-classname
*@see JDBCRealm#getDriverName()
*/
公共字符串getDriverName(){
返回jdbcRealm.getDriverName();
}
/**
*设置将要使用的JDBC驱动程序。
*
*@param driverName驱动程序名称
*@see JDBCRealm#setDriverName(字符串)
*/
公共无效setDriverName(字符串driverName){
setDriverName(driverName);
}
/**
*把那张桌子还给我
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>
<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" />
* </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);
}
}