| /* |
| * Copyright 2005-2008 Jeremy Haile |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.jsecurity.realm.ldap; |
| |
| import org.jsecurity.authc.Account; |
| import org.jsecurity.authc.AuthenticationException; |
| import org.jsecurity.authc.AuthenticationToken; |
| import org.jsecurity.authz.AuthorizingAccount; |
| import org.jsecurity.realm.AuthorizingRealm; |
| import org.jsecurity.realm.Realm; |
| import org.jsecurity.subject.PrincipalCollection; |
| import org.jsecurity.util.Initializable; |
| |
| import javax.naming.NamingException; |
| |
| /** |
| * <p>A {@link Realm} that authenticates with an LDAP |
| * server to build the Subject for a user. This implementation only returns roles for a |
| * particular user, and not permissions - but it can be subclassed to build a permission |
| * list as well.</p> |
| * |
| * <p>Implementations would need to implement the |
| * {@link #queryForLdapAccount(org.jsecurity.authc.AuthenticationToken,LdapContextFactory) queryForLdapAccount} and |
| * {@link #queryForLdapAccount(PrincipalCollection,LdapContextFactory) queryForLdapAccount} abstract methods.</p> |
| * |
| * <p>By default, this implementation will create an instance of {@link DefaultLdapContextFactory} to use for |
| * creating LDAP connections using the principalSuffix, searchBase, url, systemUsername, and systemPassword properties |
| * specified on the realm. The remaining settings use the defaults of {@link DefaultLdapContextFactory}, which are usually |
| * sufficient. If more customized connections are needed, you should inject a custom {@link LdapContextFactory}, which |
| * will cause these properties specified on the realm to be ignored.</p> |
| * |
| * @author Jeremy Haile |
| * @author Les Hazlewood |
| * @see #queryForLdapAccount(org.jsecurity.authc.AuthenticationToken, LdapContextFactory) |
| * @see #queryForLdapAccount(PrincipalCollection, LdapContextFactory) |
| * @since 0.1 |
| */ |
| public abstract class AbstractLdapRealm extends AuthorizingRealm implements Initializable { |
| |
| /*-------------------------------------------- |
| | C O N S T A N T S | |
| ============================================*/ |
| |
| |
| /*-------------------------------------------- |
| | I N S T A N C E V A R I A B L E S | |
| ============================================*/ |
| protected String principalSuffix = null; |
| |
| protected String searchBase = null; |
| |
| protected String url = null; |
| |
| protected String systemUsername = null; |
| |
| protected String systemPassword = null; |
| |
| private LdapContextFactory ldapContextFactory = null; |
| |
| /*-------------------------------------------- |
| | C O N S T R U C T O R S | |
| ============================================*/ |
| |
| /*-------------------------------------------- |
| | A C C E S S O R S / M O D I F I E R S | |
| ============================================*/ |
| |
| /*-------------------------------------------- |
| | M E T H O D S | |
| ============================================*/ |
| |
| |
| /** |
| * Used when initializing the default {@link LdapContextFactory}. This property is ignored if a custom |
| * <tt>LdapContextFactory</tt> is specified. |
| * |
| * @param principalSuffix the suffix. |
| * @see DefaultLdapContextFactory#setPrincipalSuffix(String) |
| */ |
| public void setPrincipalSuffix( String principalSuffix ) { |
| this.principalSuffix = principalSuffix; |
| } |
| |
| /** |
| * Used when initializing the default {@link LdapContextFactory}. This property is ignored if a custom |
| * <tt>LdapContextFactory</tt> is specified. |
| * |
| * @param searchBase the search base. |
| * @see DefaultLdapContextFactory#setSearchBase(String) |
| */ |
| public void setSearchBase( String searchBase ) { |
| this.searchBase = searchBase; |
| } |
| |
| /** |
| * Used when initializing the default {@link LdapContextFactory}. This property is ignored if a custom |
| * <tt>LdapContextFactory</tt> is specified. |
| * |
| * @param url the LDAP url. |
| * @see DefaultLdapContextFactory#setUrl(String) |
| */ |
| public void setUrl( String url ) { |
| this.url = url; |
| } |
| |
| /** |
| * Used when initializing the default {@link LdapContextFactory}. This property is ignored if a custom |
| * <tt>LdapContextFactory</tt> is specified. |
| * |
| * @param systemUsername the username to use when logging into the LDAP server for authorization. |
| * @see DefaultLdapContextFactory#setSystemUsername(String) |
| */ |
| public void setSystemUsername( String systemUsername ) { |
| this.systemUsername = systemUsername; |
| } |
| |
| |
| /** |
| * Used when initializing the default {@link LdapContextFactory}. This property is ignored if a custom |
| * <tt>LdapContextFactory</tt> is specified. |
| * |
| * @param systemPassword the password to use when logging into the LDAP server for authorization. |
| * @see DefaultLdapContextFactory#setSystemPassword(String) |
| */ |
| public void setSystemPassword( String systemPassword ) { |
| this.systemPassword = systemPassword; |
| } |
| |
| |
| /** |
| * Configures the {@link LdapContextFactory} implementation that is used to create LDAP connections for |
| * authentication and authorization. If this is set, the {@link LdapContextFactory} provided will be used. |
| * Otherwise, a {@link DefaultLdapContextFactory} instance will be created based on the properties specified |
| * in this realm. |
| * @param ldapContextFactory the factory to use - if not specified, a default factory will be created automatically. |
| */ |
| public void setLdapContextFactory(LdapContextFactory ldapContextFactory) { |
| this.ldapContextFactory = ldapContextFactory; |
| } |
| |
| |
| /*-------------------------------------------- |
| | M E T H O D S | |
| ============================================*/ |
| |
| protected void afterAccountCacheSet() { |
| if( ldapContextFactory == null ) { |
| |
| if( log.isDebugEnabled() ) { |
| log.debug( "No LdapContextFactory is specified, so a default instance is being created." ); |
| } |
| |
| DefaultLdapContextFactory defaultFactory = new DefaultLdapContextFactory(); |
| defaultFactory.setPrincipalSuffix( this.principalSuffix ); |
| defaultFactory.setSearchBase( this.searchBase ); |
| defaultFactory.setUrl( this.url ); |
| defaultFactory.setSystemUsername( this.systemUsername ); |
| defaultFactory.setSystemPassword( this.systemPassword ); |
| |
| ldapContextFactory = defaultFactory; |
| } |
| } |
| |
| |
| protected Account doGetAccount( AuthenticationToken token ) throws AuthenticationException { |
| Account account = null; |
| try { |
| account = queryForLdapAccount( token, this.ldapContextFactory ); |
| } catch ( NamingException e ) { |
| if ( log.isErrorEnabled() ) { |
| final String message = "LDAP naming error while attempting to authenticate user."; |
| log.error( message, e ); |
| } |
| } |
| |
| return account; |
| } |
| |
| |
| |
| |
| protected AuthorizingAccount doGetAccount( PrincipalCollection principals ) { |
| AuthorizingAccount authorizingAccount = null; |
| try { |
| authorizingAccount = queryForLdapAccount( principals, this.ldapContextFactory ); |
| } catch( NamingException e ) { |
| if ( log.isErrorEnabled() ) { |
| final String message = "LDAP naming error while attempting to retrieve authorization for user [" + principals + "]."; |
| log.error( message, e ); |
| } |
| } |
| |
| return authorizingAccount; |
| } |
| |
| |
| /** |
| * <p>Abstract method that should be implemented by subclasses to builds an |
| * {@link org.jsecurity.authc.Account} object by querying the LDAP context for the |
| * specified username.</p> |
| * |
| * @param token the authentication token given during authentication. |
| * @param ldapContextFactory factory used to retrieve LDAP connections. |
| * @return an {@link org.jsecurity.authz.SimpleAuthorizingAccount} instance containing information retrieved from the LDAP server. |
| * @throws NamingException if any LDAP errors occur during the search. |
| */ |
| protected abstract Account queryForLdapAccount( AuthenticationToken token, LdapContextFactory ldapContextFactory) throws NamingException; |
| |
| |
| /** |
| * <p>Abstract method that should be implemented by subclasses to builds an |
| * {@link org.jsecurity.authz.SimpleAuthorizingAccount} object by querying the LDAP context for the |
| * specified principal.</p> |
| * |
| * @param principal the principal of the Subject whose Account should be queried from the LDAP server. |
| * @param ldapContextFactory factory used to retrieve LDAP connections. |
| * @return an {@link org.jsecurity.authz.SimpleAuthorizingAccount} instance containing information retrieved from the LDAP server. |
| * @throws NamingException if any LDAP errors occur during the search. |
| */ |
| protected abstract AuthorizingAccount queryForLdapAccount( PrincipalCollection principal, LdapContextFactory ldapContextFactory) throws NamingException; |
| |
| } |