/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE and NOTICE files at the root of the source * tree and available online at * * http://www.dspace.org/license/ */ package org.dspace.authenticate; import javax.servlet.http.HttpServletRequest; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import org.dspace.authenticate.service.AuthenticationService; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; import org.dspace.core.factory.CoreServiceFactory; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.eperson.service.EPersonService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; /** * Access point for the stackable authentication methods. *

* This class initializes the "stack" from the DSpace configuration, * and then invokes methods in the appropriate order on behalf of clients. *

* See the AuthenticationMethod interface for details about what each * function does. *

* Configuration
* The stack of authentication methods is defined by one property in the DSpace configuration: *

 *   plugin.sequence.org.dspace.eperson.AuthenticationMethod = a list of method class names
 *     e.g.
 *   plugin.sequence.org.dspace.eperson.AuthenticationMethod = \
 *       org.dspace.eperson.X509Authentication, \
 *       org.dspace.eperson.PasswordAuthentication
 * 
*

* The "stack" is always traversed in order, with the methods * specified first (in the configuration) thus getting highest priority. * * @see AuthenticationMethod * * @author Larry Stone * @version $Revision$ */ public class AuthenticationServiceImpl implements AuthenticationService, InitializingBean { /** List of authentication methods, highest precedence first. */ protected List methodStack; /** SLF4J logging category */ private final Logger log = (Logger) LoggerFactory.getLogger(AuthenticationServiceImpl.class); @Autowired(required = true) protected EPersonService ePersonService; @Override public void afterPropertiesSet() throws Exception { methodStack = Arrays.asList((AuthenticationMethod[])CoreServiceFactory.getInstance().getPluginService().getPluginSequence(AuthenticationMethod.class)); } @Override public int authenticate(Context context, String username, String password, String realm, HttpServletRequest request) { return authenticateInternal(context, username, password, realm, request, false); } @Override public int authenticateImplicit(Context context, String username, String password, String realm, HttpServletRequest request) { return authenticateInternal(context, username, password, realm, request, true); } protected int authenticateInternal(Context context, String username, String password, String realm, HttpServletRequest request, boolean implicitOnly) { // better is lowest, so start with the highest. int bestRet = AuthenticationMethod.BAD_ARGS; // return on first success, otherwise "best" outcome. for (AuthenticationMethod aMethodStack : methodStack) { if (!implicitOnly || aMethodStack.isImplicit()) { int ret = 0; try { ret = aMethodStack.authenticate(context, username, password, realm, request); } catch (SQLException e) { ret = AuthenticationMethod.NO_SUCH_USER; } if (ret == AuthenticationMethod.SUCCESS) { EPerson me = context.getCurrentUser(); me.setLastActive(new Date()); try { ePersonService.update(context, me); } catch (SQLException ex) { log.error("Could not update last-active stamp", ex); } catch (AuthorizeException ex) { log.error("Could not update last-active stamp", ex); } return ret; } if (ret < bestRet) { bestRet = ret; } } } return bestRet; } @Override public boolean canSelfRegister(Context context, HttpServletRequest request, String username) throws SQLException { for (int i = 0; i < methodStack.size(); ++i) { if (methodStack.get(i).canSelfRegister(context, request, username)) { return true; } } return false; } @Override public boolean allowSetPassword(Context context, HttpServletRequest request, String username) throws SQLException { for (int i = 0; i < methodStack.size(); ++i) { if (methodStack.get(i).allowSetPassword(context, request, username)) { return true; } } return false; } @Override public void initEPerson(Context context, HttpServletRequest request, EPerson eperson) throws SQLException { for (AuthenticationMethod method : methodStack) { method.initEPerson(context, request, eperson); } } @Override public List getSpecialGroups(Context context, HttpServletRequest request) throws SQLException { List result = new ArrayList<>(); int totalLen = 0; for (int i = 0; i < methodStack.size(); ++i) { List gl = methodStack.get(i).getSpecialGroups(context, request); if (gl.size() > 0) { result.addAll(gl); totalLen += gl.size(); } } return result; } @Override public Iterator authenticationMethodIterator() { return methodStack.iterator(); } }