Title: JNDI & LDAP Realm for Tomcat 4.0 & Tomcat 3.2x alpha3 available: NEED YOUR FEEDBACK!

Dear tomcat users and developers,

This is an implementation of JNDI and LDAP realm for Tomcat 3 and 4
I would greatly appreciate you feedback regarding its functionality.

Alex Roytman

download from http://www.peacetech.com/java/files/apache/tomcat/

JndiRealm authenticates and authorizes users against JNDI. It was tested against LDAP JNDI
with Sun's and Netscape's jndi providers
LdapRealm authenticates and authorizes users directly against LDAP using Netscape LDAP JDK.
These two realms are interchangeable you can switch between them without many configuration changes.
According to my tests it performs 10 faster under 20 concurrent threads than JNDI with
Sun's LDAP provider. This is not final result because I need to test and tune-up multithreaded
access and synchronization there might be some misunderstanding on my part.
I also noticed some cases of JNDI loosing connection to the server under heavy multithreaded
load while Netscape's LDAP handled it nicely.
There are four classes in the package :
  JndiRealm and LdapRealm are for Tomcat 3.2x
  JndiRealmCatalina and LdapRealmCatalina for Tomcat 4.0

className="com.peacetech.webtools.tomcat.JndiRealm"           JNDI TOMCAT 3.2x
className="com.peacetech.webtools.tomcat.JndiRealmCatalina"   JNDI TOMCAT 4.0
className="com.peacetech.webtools.tomcat.LdapRealmCatalina"   LDAP TOMCAT 4.0
className="com.peacetech.webtools.tomcat.LdapRealm"           LDAP TOMCAT 3.2x

Jndi/LdapRealm uses searchBindDN and searchBindCredentials to connect to a directory.
Then it looks for exactly one user name matching searchFilter in searchBaseContext
scoped by searchScopeAsString (values are "base", "one", "sub" according to LDAP URL rules)
If one and only one matching directory object is found it will use this object and
tomcat supplied credentials to authenticate the user.
If successful Realm will fetch user roles using JNDI attributes listed in securityAttributes
(comma separated directory attribute names). If attributesReadByOwner = "true" Realm will use
authenticated user itself to pool the attributes from directory otherwise it will use searchBindDN
to retrieve the attributes.
If roleMapperClass is specified Realm will use it to map user roles onto application roles
specific for each web context for tomcat 3.2x and specific for each defined Realm for tomcat 4.2.
Provided SimpleRoleMapper implementation will read role map from either roleMapperSourceUrl
(if specified) or for tomcat 3.2x from WEB-INF/role-map.xml file in each web context
if no roleMapperSourceUrl was defined (if WEB-INF/role-map.xml file does not exist in a context
no mapping for this context will occur)


PARAMETERS:

jndiInitialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory"
                            (or "com.netscape.jndi.ldap.LdapContextFactory")
This attribute for JndiRealm ONLY.
It corresponds to javax.naming.Context.INITIAL_CONTEXT_FACTORY

directoryUrl = "ldap://207.176.93.66:389"
This attribute for both JndiRealm and LdapRealm.
It corresponds to javax.naming.Context.PROVIDER_URL

jndiSecurityAuthentication = "simple"
This attribute for JndiRealm ONLY.
It corresponds to javax.naming.Context.SECURITY_AUTHENTICATION

jndiSecurityProtocol = "" ("" vendor default or "ssl", or vendor specific)
This attribute for JndiRealm ONLY.
It corresponds to javax.naming.Context.SECURITY_PROTOCOL

searchBindDN = "cn=ldap-user,o=pti"
This attribute for both JndiRealm and LdapRealm. User name to bind to directory
a to perform user name lookups. It corresponds to javax.naming.Context.SECURITY_PRINCIPAL

searchBindCredentials = "mypassword"
This attribute for both JndiRealm and LdapRealm. Password for searchBindDN
It corresponds to javax.naming.Context.SECURITY_CREDENTIALS

searchBaseContext = "o=pti"
Base context for user lookups

ldapVersion = "3"
This attribute for LdapRealm ONLY. Defines LDAP version.

searchScopeAsString = "base" | "one" | "sub"
defines search scope "base" - object scope, "one" - one level scope, "sub" - subtree scope.

attributesReadByOwner = "true"
defines who will read securityAttribures from the directory. If "true" authenticating user account
will be used to retrieve the roles otherwise the searchBindDN account used for user name lookups will
fetch the attributes. It is useful when either one or the other do not have permission to read the
attributes so you can chose the one which has this permissions

searchFilter = "cn={0}"
Filter to lookup authorizing user. Support java.text.MessageFormat.
The only parameter is to java.text.MessageFormat pattern authorizing username.
i.e. jndiSearchFilter = "cn={0}" for user alex will result in lookup for "cn=alex"

securityAttributes = "securityEquals"
One or more directory attributes separated with semicolon which contains security roles
attributes can be multivalued. If blank no attempt to retrieve roles from directory will be done

roleMapperClass = "com.peacetech.webtools.tomcat.SimpleRoleMapper"/>
ATTNTION: It requires SAX2/JAX1.1 (Apache Xerces or Sun JAXP1.1 distribution)
Implemntation of RoleMapper interface to be used to transform user directory roles
to application roles. In tomcat 3.2x MapperClass is server wide but actual mapping data
is context specific (unless you specified roleMapperSourceUrl)
in tomcat 4.0 both RoleMapper and mapping data are Realm specific and you have to specify
roleMapperSourceUrl. If it is blank no role mapping will occur

roleMapperSourceUrl="file:///d:/tomcat4/conf/my-role-map.xml"
URL to RoleMapper source. In tomcat 3.2x if it is not specified we try to find file
WEB-INF/role-map.xml in every initializing tomcat context.

connectionMaxPoolSize = 10
JNDI does not allow multi-threaded access to a single context instance. We pool contexts which
do user filter lookup instead creating and re-authenticating every time. Access to pool
is synchronized. In LdapPrincipal factory we pool user connection so we reauthenticate without reconnecting

SAMPLES:

TOMCAT 4:
<Realm className="com.peacetech.webtools.tomcat.LdapRealmCatalina"
  debug="1"
  directoryUrl = "ldap://207.176.93.66:389"
  searchBindDN = "cn=ldap-user,o=pti"
  searchBindCredentials = "mypassword"
  searchBaseContext = "o=pti"
  searchFilter = "cn={0}"
  searchScopeAsString = "sub"
  securityAttributes = "securityEquals"
  attributesReadByOwner = "true"
  connectionMaxPoolSize = "10"
  ldapVersion = "3"
  roleMapperClass = "com.peacetech.webtools.tomcat.SimpleRoleMapper"
  roleMapperSourceUrl="file:///z:/Projects/Gao/gwiz/web/gwiz/WEB-INF/role-map.xml" />

<Realm className="com.peacetech.webtools.tomcat.JndiRealmCatalina"
  debug="1"
  jndiInitialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory"
  jndiSecurityAuthentication = "simple"
  directoryUrl = "ldap://207.176.93.66:389"
  jndiSecurityProtocol = ""
  searchBindDN = "cn=ldap-user,o=pti"
  searchBindCredentials = "mypassword"
  searchBaseContext = "o=pti"
  searchFilter = "cn={0}"
  searchScopeAsString = "sub"
  securityAttributes = "securityEquals"
  attributesReadByOwner = "true"
  connectionMaxPoolSize = "10"
  roleMapperClass = "com.peacetech.webtools.tomcat.SimpleRoleMapper"
  roleMapperSourceUrl="file:///z:/Projects/Gao/gwiz/web/gwiz/WEB-INF/role-map.xml" />



TOMCAT 3:
<RequestInterceptor className="com.peacetech.webtools.tomcat.LdapRealm"
  debug="1"
  directoryUrl = "ldap://207.176.93.66:389"
  searchBindDN = "cn=ldap-user,o=pti"
  searchBindCredentials = "mypassword"
  searchBaseContext = "o=pti"
  searchFilter = "cn={0}"
  searchScopeAsString = "sub"
  securityAttributes = "securityEquals"
  attributesReadByOwner = "true"
  connectionMaxPoolSize = "10"
  ldapVersion = "3"
  roleMapperClass = "com.peacetech.webtools.tomcat.SimpleRoleMapper"
  roleMapperSourceUrl="file:///z:/Projects/Gao/gwiz/web/gwiz/WEB-INF/role-map.xml" />

<RequestInterceptor className="com.peacetech.webtools.tomcat.JndiRealm"
  debug="1"
  jndiInitialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory"
  jndiSecurityAuthentication = "simple"
  directoryUrl = "ldap://207.176.93.66:389"
  jndiSecurityProtocol = ""
  searchBindDN = "cn=ldap-user,o=pti"
  searchBindCredentials = "mypassword"
  searchBaseContext = "o=pti"
  searchFilter = "cn={0}"
  searchScopeAsString = "sub"
  securityAttributes = "securityEquals"
  attributesReadByOwner = "true"
  connectionMaxPoolSize = "10"
  roleMapperClass = "com.peacetech.webtools.tomcat.SimpleRoleMapper"
  roleMapperSourceUrl="file:///z:/Projects/Gao/gwiz/web/gwiz/WEB-INF/role-map.xml" />


Reply via email to