PreAuthTokenProcessingFilter.java
package cn.home1.oss.lib.security.internal.preauth;
import static cn.home1.oss.lib.security.internal.preauth.PreAuthTokenFilter.ATTR_PRINCIPAL;
import static cn.home1.oss.lib.security.internal.preauth.PreAuthTokenFilter.ATTR_PRINCIPAL_TOKEN;
import static lombok.AccessLevel.PROTECTED;
import cn.home1.oss.lib.security.api.GenericUser;
import cn.home1.oss.lib.security.api.Security;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.NullRememberMeServices;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.web.filter.GenericFilterBean;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Not a bean, avoid auto pick-up.
* after BasicAuthenticationFilter and PreAuthTestUserFilter.
* see: BasicAuthenticationFilter or AbstractPreAuthenticatedProcessingFilter
*
* <p>authenticate against the supplied {@code AuthenticationManager}
* and use the supplied {@code AuthenticationEntryPoint} to handle authentication failures.</p>
*
* @author zhanghaolun
*/
@Setter
@Getter(value = PROTECTED)
@Slf4j
@SuppressWarnings("PMD.ImmutableField")
public class PreAuthTokenProcessingFilter extends GenericFilterBean {
/**
* will be invoked when authentication fails. Typically an instance of
* {@link org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint}.
*/
private AuthenticationEntryPoint authenticationEntryPoint;
/**
* the bean to submit authentication requests to.
*/
private AuthenticationManager authenticationManager;
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;
private RememberMeServices rememberMeServices;
public PreAuthTokenProcessingFilter() {
super();
this.authenticationEntryPoint = null;
this.authenticationManager = new NoOpAuthenticationManager();
this.authenticationDetailsSource = new WebAuthenticationDetailsSource();
this.rememberMeServices = new NullRememberMeServices();
}
@Override
public void doFilter( //
final ServletRequest req, //
final ServletResponse res, //
final FilterChain chain //
) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
try {
if (this.authenticationIsRequired()) {
final GenericUser principal = (GenericUser) request.getAttribute(ATTR_PRINCIPAL);
final String token = (String) request.getAttribute(ATTR_PRINCIPAL_TOKEN);
request.removeAttribute(ATTR_PRINCIPAL);
request.removeAttribute(ATTR_PRINCIPAL_TOKEN);
final AbstractAuthenticationToken authRequest = this.attempAuthentication(request, principal, token);
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
final Authentication authResult = this.authenticationManager.authenticate(authRequest);
if (log.isTraceEnabled()) {
log.trace("AUTH authentication success: {}, principal: {}", authResult, principal);
}
final SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authResult);
this.rememberMeServices.loginSuccess(request, response, authResult);
this.onSuccessfulAuthentication(request, response, authResult);
}
} catch (final AuthenticationException failed) {
SecurityContextHolder.clearContext();
if (log.isTraceEnabled()) {
log.trace("AUTH authentication failed. not login.", failed);
}
this.rememberMeServices.loginFail(request, response);
this.onUnsuccessfulAuthentication(request, response, failed);
if (this.getIgnoreFailure()) {
chain.doFilter(request, response);
} else {
this.authenticationEntryPoint.commence(request, response, failed);
}
return;
}
chain.doFilter(request, response);
}
private boolean authenticationIsRequired() {
return Security.authenticationIsRequired();
}
@SuppressWarnings({"PMD.UnusedFormalParameter", "squid:S1172"})
private AbstractAuthenticationToken attempAuthentication( //
final HttpServletRequest request, //
final GenericUser principal, //
final String token
) {
return new PreAuthenticatedAuthenticationToken(principal, token);
}
@SuppressWarnings({"squid:S1172"})
protected void onSuccessfulAuthentication( //
final HttpServletRequest request, //
final HttpServletResponse response, //
final Authentication authResult //
) throws IOException {
// Do nothing
}
@SuppressWarnings({"squid:S1172"})
protected void onUnsuccessfulAuthentication( //
final HttpServletRequest request, //
final HttpServletResponse response, //
final AuthenticationException failed //
) throws IOException {
// Do nothing
}
public Boolean getIgnoreFailure() {
return this.authenticationEntryPoint == null;
}
@Autowired
@Override
public void setEnvironment(final Environment environment) {
super.setEnvironment(environment);
}
public static class NoOpAuthenticationManager implements AuthenticationManager {
@Override
public Authentication authenticate(final Authentication authentication) {
return authentication;
}
}
}