PreAuthTokenProcessingFilter.java

  1. package cn.home1.oss.lib.security.internal.preauth;

  2. import static cn.home1.oss.lib.security.internal.preauth.PreAuthTokenFilter.ATTR_PRINCIPAL;
  3. import static cn.home1.oss.lib.security.internal.preauth.PreAuthTokenFilter.ATTR_PRINCIPAL_TOKEN;
  4. import static lombok.AccessLevel.PROTECTED;

  5. import cn.home1.oss.lib.security.api.GenericUser;
  6. import cn.home1.oss.lib.security.api.Security;

  7. import lombok.Getter;
  8. import lombok.Setter;
  9. import lombok.extern.slf4j.Slf4j;

  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.core.env.Environment;
  12. import org.springframework.security.authentication.AbstractAuthenticationToken;
  13. import org.springframework.security.authentication.AuthenticationDetailsSource;
  14. import org.springframework.security.authentication.AuthenticationManager;
  15. import org.springframework.security.core.Authentication;
  16. import org.springframework.security.core.AuthenticationException;
  17. import org.springframework.security.core.context.SecurityContext;
  18. import org.springframework.security.core.context.SecurityContextHolder;
  19. import org.springframework.security.web.AuthenticationEntryPoint;
  20. import org.springframework.security.web.authentication.NullRememberMeServices;
  21. import org.springframework.security.web.authentication.RememberMeServices;
  22. import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
  23. import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
  24. import org.springframework.web.filter.GenericFilterBean;

  25. import java.io.IOException;

  26. import javax.servlet.FilterChain;
  27. import javax.servlet.ServletException;
  28. import javax.servlet.ServletRequest;
  29. import javax.servlet.ServletResponse;
  30. import javax.servlet.http.HttpServletRequest;
  31. import javax.servlet.http.HttpServletResponse;

  32. /**
  33.  * Not a bean, avoid auto pick-up.
  34.  * after BasicAuthenticationFilter and PreAuthTestUserFilter.
  35.  * see: BasicAuthenticationFilter or AbstractPreAuthenticatedProcessingFilter
  36.  *
  37.  * <p>authenticate against the supplied {@code AuthenticationManager}
  38.  * and use the supplied {@code AuthenticationEntryPoint} to handle authentication failures.</p>
  39.  *
  40.  * @author zhanghaolun
  41.  */
  42. @Setter
  43. @Getter(value = PROTECTED)
  44. @Slf4j
  45. @SuppressWarnings("PMD.ImmutableField")
  46. public class PreAuthTokenProcessingFilter extends GenericFilterBean {

  47.   /**
  48.    * will be invoked when authentication fails. Typically an instance of
  49.    * {@link org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint}.
  50.    */
  51.   private AuthenticationEntryPoint authenticationEntryPoint;
  52.   /**
  53.    * the bean to submit authentication requests to.
  54.    */
  55.   private AuthenticationManager authenticationManager;
  56.   private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;
  57.   private RememberMeServices rememberMeServices;

  58.   public PreAuthTokenProcessingFilter() {
  59.     super();

  60.     this.authenticationEntryPoint = null;
  61.     this.authenticationManager = new NoOpAuthenticationManager();

  62.     this.authenticationDetailsSource = new WebAuthenticationDetailsSource();
  63.     this.rememberMeServices = new NullRememberMeServices();
  64.   }

  65.   @Override
  66.   public void doFilter( //
  67.     final ServletRequest req, //
  68.     final ServletResponse res, //
  69.     final FilterChain chain //
  70.   ) throws IOException, ServletException {
  71.     final HttpServletRequest request = (HttpServletRequest) req;
  72.     final HttpServletResponse response = (HttpServletResponse) res;

  73.     try {
  74.       if (this.authenticationIsRequired()) {
  75.         final GenericUser principal = (GenericUser) request.getAttribute(ATTR_PRINCIPAL);
  76.         final String token = (String) request.getAttribute(ATTR_PRINCIPAL_TOKEN);
  77.         request.removeAttribute(ATTR_PRINCIPAL);
  78.         request.removeAttribute(ATTR_PRINCIPAL_TOKEN);

  79.         final AbstractAuthenticationToken authRequest = this.attempAuthentication(request, principal, token);
  80.         authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));

  81.         final Authentication authResult = this.authenticationManager.authenticate(authRequest);

  82.         if (log.isTraceEnabled()) {
  83.           log.trace("AUTH authentication success: {}, principal: {}", authResult, principal);
  84.         }

  85.         final SecurityContext securityContext = SecurityContextHolder.getContext();
  86.         securityContext.setAuthentication(authResult);
  87.         this.rememberMeServices.loginSuccess(request, response, authResult);
  88.         this.onSuccessfulAuthentication(request, response, authResult);
  89.       }
  90.     } catch (final AuthenticationException failed) {
  91.       SecurityContextHolder.clearContext();

  92.       if (log.isTraceEnabled()) {
  93.         log.trace("AUTH authentication failed. not login.", failed);
  94.       }

  95.       this.rememberMeServices.loginFail(request, response);
  96.       this.onUnsuccessfulAuthentication(request, response, failed);
  97.       if (this.getIgnoreFailure()) {
  98.         chain.doFilter(request, response);
  99.       } else {
  100.         this.authenticationEntryPoint.commence(request, response, failed);
  101.       }
  102.       return;
  103.     }

  104.     chain.doFilter(request, response);
  105.   }

  106.   private boolean authenticationIsRequired() {
  107.     return Security.authenticationIsRequired();
  108.   }

  109.   @SuppressWarnings({"PMD.UnusedFormalParameter", "squid:S1172"})
  110.   private AbstractAuthenticationToken attempAuthentication( //
  111.     final HttpServletRequest request, //
  112.     final GenericUser principal, //
  113.     final String token
  114.   ) {
  115.     return new PreAuthenticatedAuthenticationToken(principal, token);
  116.   }

  117.   @SuppressWarnings({"squid:S1172"})
  118.   protected void onSuccessfulAuthentication( //
  119.     final HttpServletRequest request, //
  120.     final HttpServletResponse response, //
  121.     final Authentication authResult //
  122.   ) throws IOException {
  123.     // Do nothing
  124.   }

  125.   @SuppressWarnings({"squid:S1172"})
  126.   protected void onUnsuccessfulAuthentication( //
  127.     final HttpServletRequest request, //
  128.     final HttpServletResponse response, //
  129.     final AuthenticationException failed //
  130.   ) throws IOException {
  131.     // Do nothing
  132.   }

  133.   public Boolean getIgnoreFailure() {
  134.     return this.authenticationEntryPoint == null;
  135.   }

  136.   @Autowired
  137.   @Override
  138.   public void setEnvironment(final Environment environment) {
  139.     super.setEnvironment(environment);
  140.   }

  141.   public static class NoOpAuthenticationManager implements AuthenticationManager {

  142.     @Override
  143.     public Authentication authenticate(final Authentication authentication) {
  144.       return authentication;
  145.     }
  146.   }
  147. }