/** * 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.annotation.Autowired; /** * Access point for the stackable authentication methods. * <p> * This class initializes the "stack" from the DSpace configuration, * and then invokes methods in the appropriate order on behalf of clients. * <p> * See the AuthenticationMethod interface for details about what each * function does. * <p> * <b>Configuration</b><br> * The stack of authentication methods is defined by one property in the DSpace configuration: * <pre> * plugin.sequence.org.dspace.eperson.AuthenticationMethod = <em>a list of method class names</em> * <em>e.g.</em> * plugin.sequence.org.dspace.eperson.AuthenticationMethod = \ * org.dspace.eperson.X509Authentication, \ * org.dspace.eperson.PasswordAuthentication * </pre> * <p> * 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 { /** SLF4J logging category */ private final Logger log = (Logger) LoggerFactory.getLogger(AuthenticationServiceImpl.class); @Autowired(required = true) protected EPersonService ePersonService; protected AuthenticationServiceImpl() { } public List<AuthenticationMethod> getAuthenticationMethodStack() { return 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 : getAuthenticationMethodStack()) { 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 (AuthenticationMethod method : getAuthenticationMethodStack()) { if (method.canSelfRegister(context, request, username)) { return true; } } return false; } @Override public boolean allowSetPassword(Context context, HttpServletRequest request, String username) throws SQLException { for (AuthenticationMethod method : getAuthenticationMethodStack()) { if (method.allowSetPassword(context, request, username)) { return true; } } return false; } @Override public void initEPerson(Context context, HttpServletRequest request, EPerson eperson) throws SQLException { for (AuthenticationMethod method : getAuthenticationMethodStack()) { method.initEPerson(context, request, eperson); } } @Override public List<Group> getSpecialGroups(Context context, HttpServletRequest request) throws SQLException { List<Group> result = new ArrayList<>(); int totalLen = 0; for (AuthenticationMethod method : getAuthenticationMethodStack()) { List<Group> gl = method.getSpecialGroups(context, request); if (gl.size() > 0) { result.addAll(gl); totalLen += gl.size(); } } return result; } @Override public Iterator<AuthenticationMethod> authenticationMethodIterator() { return getAuthenticationMethodStack().iterator(); } }