package fr.mch.mdo.restaurant.business.managers.authentication.jaas; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginException; import fr.mch.mdo.logs.ILogger; import fr.mch.mdo.restaurant.dao.DaoServicesFactory; import fr.mch.mdo.restaurant.dao.authentication.AuthenticationPasswordLevel; import fr.mch.mdo.restaurant.dao.beans.UserAuthenticationJaas; import fr.mch.mdo.restaurant.dao.users.ILoginUserAuthenticationsDao; import fr.mch.mdo.restaurant.exception.MdoAuthenticationException; import fr.mch.mdo.restaurant.services.authentication.jaas.LevelPasswordMdoCallback; import fr.mch.mdo.restaurant.services.authentication.jaas.NameMdoCallback; import fr.mch.mdo.restaurant.services.authentication.jaas.PasswordMdoCallback; import fr.mch.mdo.restaurant.services.authorization.jaas.TypedPrincipal; import fr.mch.mdo.restaurant.services.business.managers.authentication.jaas.ILoginDataBaseManager; import fr.mch.mdo.restaurant.services.logs.LoggerServiceImpl; /** * @author Mathieu MA * * To change this generated comment edit the template variable * "typecomment": Window>Preferences>Java>Templates. To enable and * disable the creation of type comments go to * Window>Preferences>Java>Code Generation. */ public class DefaultLoginDataBaseManager implements ILoginDataBaseManager { // initial state private Subject subject; private CallbackHandler callbackHandler; @SuppressWarnings("unused") private Map<String, ?> sharedState; @SuppressWarnings("unused") private Map<String, ?> options; private UserAuthenticationJaas userAuthentication = null; private ILogger logger = null; protected ILoginUserAuthenticationsDao dao; public DefaultLoginDataBaseManager() { // Instantiate by JAAS from new LoginContext logger = LoggerServiceImpl.getInstance().getLogger(DefaultLoginDataBaseManager.class.getName()); dao = DaoServicesFactory.getUserAuthenticationsDao(); } /** * Initialize this <code>LoginModule</code>. * * <p> * * @param subject * the <code>Subject</code> to be authenticated. * <p> * * @param callbackHandler * a <code>CallbackHandler</code> for communicating with the end * user (prompting for usernames and passwords, for example). * <p> * * @param sharedState * shared <code>LoginModule</code> state. * <p> * * @param options * options specified in the login <code>Configuration</code> for * this particular <code>LoginModule</code>. */ @Override public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) { this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = sharedState; this.options = options; // initialize any configured options // boolean debug = "true".equalsIgnoreCase((String) // options.get("debug")); } /** * Authenticate the user by prompting for a username and password. * * <p> * * @return true in all cases since this <code>LoginModule</code> should not * be ignored. * * @exception FailedLoginException * if the authentication fails. * <p> * * @exception LoginException * if this <code>LoginModule</code> is unable to perform the * authentication. */ public boolean login() throws LoginException { Callback callbacks[] = new Callback[3]; callbacks[0] = new NameMdoCallback(); callbacks[1] = new PasswordMdoCallback(); callbacks[2] = new LevelPasswordMdoCallback(); try { callbackHandler.handle(callbacks); String login = ((NameCallback) callbacks[0]).getName(); char password[] = ((PasswordCallback) callbacks[1]).getPassword(); AuthenticationPasswordLevel levelPassword = ((LevelPasswordMdoCallback) callbacks[2]).getLevelPassword(); userAuthentication = (UserAuthenticationJaas) dao.findByLogin(login); if (userAuthentication == null) { // No need to log because this catching exception will do throw new MdoAuthenticationException("message.error.authentication.login.no.user"); } // levelPassword and password are never null here // because callbackHandler.handle will rise an exception String userPassword = levelPassword.getPassword(userAuthentication); if (!new String(password).equals(userPassword)) { // No need to log because this catching exception will do throw new MdoAuthenticationException("message.error.authentication.login.wrong.password"); } } catch (Exception e) { logger.fatal(e.getLocalizedMessage()); return false; } return true; } /** * <p> * This method is called if the LoginContext's overall authentication * succeeded (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL * LoginModules succeeded). * * <p> * If this LoginModule's own authentication attempt succeeded (checked by * retrieving the private state saved by the <code>login</code> method), * then this method associates a <code>SamplePrincipal</code> with the * <code>Subject</code> located in the <code>LoginModule</code>. If this * LoginModule's own authentication attempted failed, then this method * removes any state that was originally saved. * * <p> * * @exception LoginException * if the commit fails. * * @return true if this LoginModule's own login and commit attempts * succeeded, or false otherwise. */ public boolean commit() throws LoginException { // add a Principal (authenticated identity) // to the Subject // assume the user we authenticated is the SamplePrincipal TypedPrincipal userPrincipal; if (userAuthentication != null && userAuthentication.getUserRole() != null && userAuthentication.getUserRole().getCode() != null && userAuthentication.getUserRole().getCode().getName() != null) { userPrincipal = new TypedPrincipal(userAuthentication.getUserRole().getCode().getName()); } else { return false; } if (subject != null && subject.getPrincipals() != null) { if (!subject.getPrincipals().contains(userPrincipal)) { subject.getPrincipals().add(userPrincipal); } } else { return false; } return true; } /** * <p> * This method is called if the LoginContext's overall authentication * failed. (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL * LoginModules did not succeed). * * <p> * If this LoginModule's own authentication attempt succeeded (checked by * retrieving the private state saved by the <code>login</code> and * <code>commit</code> methods), then this method cleans up any state that * was originally saved. * * <p> * * @exception LoginException * if the abort fails. * * @return false if this LoginModule's own login and/or commit attempts * failed, and true otherwise. */ public boolean abort() throws LoginException { return true; } /** * Logout the user. * * <p> * This method removes the <code>SamplePrincipal</code> that was added by * the <code>commit</code> method. * * <p> * * @exception LoginException * if the logout fails. * * @return true in all cases since this <code>LoginModule</code> should not * be ignored. */ public boolean logout() throws LoginException { return true; } }