Package org.beangle.security.auth.dao

Source Code of org.beangle.security.auth.dao.AbstractUserDetailAuthenticationProvider$DefaultPostAuthenticationChecker

/* Copyright c 2005-2012.
* Licensed under GNU  LESSER General Public License, Version 3.
* http://www.gnu.org/licenses
*/
package org.beangle.security.auth.dao;

import org.beangle.security.auth.AccountExpiredException;
import org.beangle.security.auth.AuthenticationProvider;
import org.beangle.security.auth.CredentialsExpiredException;
import org.beangle.security.auth.DisabledException;
import org.beangle.security.auth.LockedException;
import org.beangle.security.auth.UsernamePasswordAuthentication;
import org.beangle.security.core.Authentication;
import org.beangle.security.core.AuthenticationException;
import org.beangle.security.core.userdetail.UserDetail;
import org.beangle.security.core.userdetail.UserDetailChecker;
import org.beangle.security.core.userdetail.UsernameNotFoundException;

public abstract class AbstractUserDetailAuthenticationProvider implements AuthenticationProvider {
  private boolean forcePrincipalAsString = false;
  private UserDetailChecker preAuthenticationChecker = new DefaultPreAuthenticationChecker();
  private UserDetailChecker postAuthenticationChecker = new DefaultPostAuthenticationChecker();

  protected abstract void additionalAuthenticationChecks(UserDetail userDetails,
      Authentication authentication) throws AuthenticationException;

  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    // Determine username
    String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication
        .getName();

    UserDetail user = retrieveUser(username, authentication);

    if (null == user) { throw new UsernameNotFoundException(); }
    preAuthenticationChecker.check(user);

    additionalAuthenticationChecks(user, authentication);

    postAuthenticationChecker.check(user);

    Object principalToReturn = user;

    if (forcePrincipalAsString) {
      principalToReturn = user.getUsername();
    }

    return createSuccessAuthentication(principalToReturn, authentication, user);
  }

  protected Authentication createSuccessAuthentication(Object principal, Authentication authentication,
      UserDetail user) {
    UsernamePasswordAuthentication result = new UsernamePasswordAuthentication(principal,
        authentication.getCredentials(), user.getAuthorities());
    result.setDetails(authentication.getDetails());
    return result;
  }

  protected void doAfterPropertiesSet() throws Exception {
  }

  public boolean isForcePrincipalAsString() {
    return forcePrincipalAsString;
  }

  /**
   * Allows subclasses to actually retrieve the <code>UserDetails</code> from
   * an implementation-specific location, with the option of throwing an
   * <code>AuthenticationException</code> immediately if the presented
   * credentials are incorrect (this is especially useful if it is necessary
   * to bind to a resource as the user in order to obtain or generate a <code>UserDetails</code>).
   * <p>
   * Subclasses are not required to perform any caching, as the
   * <code>AbstractUserDetailsAuthenticationProvider</code> will by default cache the
   * <code>UserDetails</code>. The caching of <code>UserDetails</code> does present additional
   * complexity as this means subsequent requests that rely on the cache will need to still have
   * their credentials validated, even if the correctness of credentials was assured by subclasses
   * adopting a binding-based strategy in this method. Accordingly it is important that subclasses
   * either disable caching (if they want to ensure that this method is the only method that is
   * capable of authenticating a request, as no <code>UserDetails</code> will ever be cached) or
   * ensure subclasses implement
   * {@link #additionalAuthenticationChecks(UserDetail, UsernamePasswordAuthentication)} to
   * compare the credentials of a cached <code>UserDetails</code> with subsequent authentication
   * requests.
   * </p>
   * <p>
   * Most of the time subclasses will not perform credentials inspection in this method, instead
   * performing it in
   * {@link #additionalAuthenticationChecks(UserDetail, UsernamePasswordAuthentication)} so that
   * code related to credentials validation need not be duplicated across two methods.
   * </p>
   *
   * @param username
   *            The username to retrieve
   * @param authentication
   *            The authentication request, which subclasses <em>may</em> need
   *            to perform a binding-based retrieval of the <code>UserDetails</code>
   * @return the user information (never <code>null</code> - instead an
   *         exception should the thrown)
   * @throws AuthenticationException
   *             if the credentials could not be validated (generally a
   *             <code>BadCredentialsException</code>, an
   *             <code>AuthenticationServiceException</code> or
   *             <code>UsernameNotFoundException</code>)
   */
  protected abstract UserDetail retrieveUser(String username, Authentication authentication)
      throws AuthenticationException;

  public void setForcePrincipalAsString(boolean forcePrincipalAsString) {
    this.forcePrincipalAsString = forcePrincipalAsString;
  }

  public boolean supports(Class<? extends Authentication> authentication) {
    return (UsernamePasswordAuthentication.class.isAssignableFrom(authentication));
  }

  protected UserDetailChecker getPreAuthenticationChecks() {
    return preAuthenticationChecker;
  }

  /**
   * Sets the policy will be used to verify the status of the loaded <tt>UserDetails</tt>
   * <em>before</em> validation of the credentials takes
   * place.
   *
   * @param preAuthenticationChecks
   *            strategy to be invoked prior to authentication.
   */
  public void setPreAuthenticationChecks(UserDetailChecker preAuthenticationChecks) {
    this.preAuthenticationChecker = preAuthenticationChecks;
  }

  protected UserDetailChecker getPostAuthenticationChecks() {
    return postAuthenticationChecker;
  }

  public void setPostAuthenticationChecks(UserDetailChecker postAuthenticationChecks) {
    this.postAuthenticationChecker = postAuthenticationChecks;
  }

  private class DefaultPreAuthenticationChecker implements UserDetailChecker {
    public void check(UserDetail user) {
      if (user.isAccountLocked()) { throw new LockedException(null, user); }

      if (!user.isEnabled()) { throw new DisabledException(null, user); }

      if (user.isAccountExpired()) { throw new AccountExpiredException(null, user); }
    }
  }

  private class DefaultPostAuthenticationChecker implements UserDetailChecker {
    public void check(UserDetail user) {
      if (user.isCredentialsExpired()) { throw new CredentialsExpiredException(null, user); }
    }
  }

}
TOP

Related Classes of org.beangle.security.auth.dao.AbstractUserDetailAuthenticationProvider$DefaultPostAuthenticationChecker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.