summaryrefslogtreecommitdiffstats
path: root/archiva-modules/archiva-web/archiva-web-common
diff options
context:
space:
mode:
authorOlivier Lamy <olamy@apache.org>2012-12-13 08:39:38 +0000
committerOlivier Lamy <olamy@apache.org>2012-12-13 08:39:38 +0000
commitc6ba1194aaa151e2ed9c10b6fa946891330efd59 (patch)
tree3ef03af042e2bfdcaa7329f109f84437602d2bca /archiva-modules/archiva-web/archiva-web-common
parent374cacbd7771a7cd092469d95429a5d329cf5ef7 (diff)
downloadarchiva-c6ba1194aaa151e2ed9c10b6fa946891330efd59.tar.gz
archiva-c6ba1194aaa151e2ed9c10b6fa946891330efd59.zip
[MRM-1721] chaining user manager implementation
git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1421133 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'archiva-modules/archiva-web/archiva-web-common')
-rw-r--r--archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/security/ArchivaUserManagerAuthenticator.java199
1 files changed, 199 insertions, 0 deletions
diff --git a/archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/security/ArchivaUserManagerAuthenticator.java b/archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/security/ArchivaUserManagerAuthenticator.java
new file mode 100644
index 000000000..789c93804
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/security/ArchivaUserManagerAuthenticator.java
@@ -0,0 +1,199 @@
+package org.apache.archiva.web.security;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.archiva.admin.model.RepositoryAdminException;
+import org.apache.archiva.admin.model.runtime.ArchivaRuntimeConfigurationAdmin;
+import org.apache.archiva.redback.authentication.AuthenticationConstants;
+import org.apache.archiva.redback.authentication.AuthenticationDataSource;
+import org.apache.archiva.redback.authentication.AuthenticationException;
+import org.apache.archiva.redback.authentication.AuthenticationResult;
+import org.apache.archiva.redback.authentication.PasswordBasedAuthenticationDataSource;
+import org.apache.archiva.redback.authentication.users.UserManagerAuthenticator;
+import org.apache.archiva.redback.policy.AccountLockedException;
+import org.apache.archiva.redback.policy.MustChangePasswordException;
+import org.apache.archiva.redback.policy.PasswordEncoder;
+import org.apache.archiva.redback.policy.UserSecurityPolicy;
+import org.apache.archiva.redback.users.User;
+import org.apache.archiva.redback.users.UserManager;
+import org.apache.archiva.redback.users.UserManagerException;
+import org.apache.archiva.redback.users.UserNotFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Olivier Lamy
+ * @since 1.4-M4
+ */
+@Service( "authenticator#archiva" )
+public class ArchivaUserManagerAuthenticator
+ extends UserManagerAuthenticator
+{
+ private Logger log = LoggerFactory.getLogger( getClass() );
+
+ @Inject
+ private UserSecurityPolicy securityPolicy;
+
+ @Inject
+ private ApplicationContext applicationContext;
+
+ @Inject
+ private ArchivaRuntimeConfigurationAdmin archivaRuntimeConfigurationAdmin;
+
+ private List<UserManager> userManagers;
+
+ @PostConstruct
+ protected void initialize()
+ throws RepositoryAdminException
+ {
+ List<String> userManagerImpls =
+ archivaRuntimeConfigurationAdmin.getArchivaRuntimeConfiguration().getUserManagerImpls();
+
+ userManagers = new ArrayList<UserManager>( userManagerImpls.size() );
+
+ for ( String beanId : userManagerImpls )
+ {
+ userManagers.add( applicationContext.getBean( "userManager#" + beanId, UserManager.class ) );
+ }
+ }
+
+
+ @Override
+ public AuthenticationResult authenticate( AuthenticationDataSource ds )
+ throws AuthenticationException, AccountLockedException, MustChangePasswordException
+ {
+ boolean authenticationSuccess = false;
+ String username = null;
+ Exception resultException = null;
+ PasswordBasedAuthenticationDataSource source = (PasswordBasedAuthenticationDataSource) ds;
+ Map<String, String> authnResultExceptionsMap = new HashMap<String, String>();
+
+ for ( UserManager userManager : userManagers )
+ {
+ try
+ {
+ log.debug( "Authenticate: {} with userManager: {}", source, userManager.getId() );
+ User user = userManager.findUser( source.getPrincipal() );
+ username = user.getUsername();
+
+ if ( user.isLocked() )
+ {
+ //throw new AccountLockedException( "Account " + source.getPrincipal() + " is locked.", user );
+ AccountLockedException e =
+ new AccountLockedException( "Account " + source.getPrincipal() + " is locked.", user );
+ log.warn( "{}", e.getMessage() );
+ resultException = e;
+ authnResultExceptionsMap.put( AuthenticationConstants.AUTHN_LOCKED_USER_EXCEPTION, e.getMessage() );
+ }
+
+ if ( user.isPasswordChangeRequired() && source.isEnforcePasswordChange() )
+ {
+ //throw new MustChangePasswordException( "Password expired.", user );
+ MustChangePasswordException e = new MustChangePasswordException( "Password expired.", user );
+ log.warn( "{}", e.getMessage() );
+ resultException = e;
+ authnResultExceptionsMap.put( AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION,
+ e.getMessage() );
+ }
+
+ PasswordEncoder encoder = securityPolicy.getPasswordEncoder();
+ log.debug( "PasswordEncoder: {}", encoder.getClass().getName() );
+
+ boolean isPasswordValid = encoder.isPasswordValid( user.getEncodedPassword(), source.getPassword() );
+ if ( isPasswordValid )
+ {
+ log.debug( "User {} provided a valid password", source.getPrincipal() );
+
+ try
+ {
+ securityPolicy.extensionPasswordExpiration( user );
+
+ authenticationSuccess = true;
+
+ //REDBACK-151 do not make unnessesary updates to the user object
+ if ( user.getCountFailedLoginAttempts() > 0 )
+ {
+ user.setCountFailedLoginAttempts( 0 );
+ userManager.updateUser( user );
+ }
+
+ return new AuthenticationResult( true, source.getPrincipal(), null );
+ }
+ catch ( MustChangePasswordException e )
+ {
+ user.setPasswordChangeRequired( true );
+ //throw e;
+ resultException = e;
+ authnResultExceptionsMap.put( AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION,
+ e.getMessage() );
+ }
+ }
+ else
+ {
+ log.warn( "Password is Invalid for user {}.", source.getPrincipal() );
+ authnResultExceptionsMap.put( AuthenticationConstants.AUTHN_NO_SUCH_USER,
+ "Password is Invalid for user " + source.getPrincipal() + "." );
+
+ try
+ {
+ securityPolicy.extensionExcessiveLoginAttempts( user );
+ }
+ finally
+ {
+ userManager.updateUser( user );
+ }
+
+ //return new AuthenticationResult( false, source.getPrincipal(), null, authnResultExceptionsMap );
+ }
+ }
+ catch ( UserNotFoundException e )
+ {
+ log.warn( "Login for user {} failed. user not found.", source.getPrincipal() );
+ resultException = e;
+ authnResultExceptionsMap.put( AuthenticationConstants.AUTHN_NO_SUCH_USER,
+ "Login for user " + source.getPrincipal() + " failed. user not found." );
+ }
+ catch ( UserManagerException e )
+ {
+ log.warn( "Login for user {} failed, message: {}", source.getPrincipal(), e.getMessage() );
+ resultException = e;
+ authnResultExceptionsMap.put( AuthenticationConstants.AUTHN_RUNTIME_EXCEPTION,
+ "Login for user " + source.getPrincipal() + " failed, message: "
+ + e.getMessage() );
+ }
+ }
+ return new AuthenticationResult( authenticationSuccess, username, resultException, authnResultExceptionsMap );
+ }
+
+ @Override
+ public String getId()
+ {
+ return "ArchivaUserManagerAuthenticator";
+ }
+}