Set details on authentication token created by HttpServlet3RequestFactory
Currently the login mechanism when triggered by executing HttpServlet3RequestFactory#login does not set any details on the underlying authentication token that is authenticated. This change adds an AuthenticationDetailsSource on the HttpServlet3RequestFactory, which defaults to a WebAuthenticationDetailsSource. Closes gh-9579
This commit is contained in:
parent
074e38d565
commit
925d531cbe
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
|
@ -90,6 +91,11 @@ public final class ServletApiConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (trustResolver != null) {
|
||||
this.securityContextRequestFilter.setTrustResolver(trustResolver);
|
||||
}
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = http
|
||||
.getSharedObject(AuthenticationDetailsSource.class);
|
||||
if (authenticationDetailsSource != null) {
|
||||
this.securityContextRequestFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
}
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
if (context != null) {
|
||||
String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
|
@ -149,6 +150,15 @@ public class ServletApiConfigurerTests {
|
|||
verify(SharedTrustResolverConfig.TR, atLeastOnce()).isAnonymous(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenSharedObjectAuthenticationDetailsSourceThenAuthenticationDetailsSourceUsed() {
|
||||
this.spring.register(SharedAuthenticationDetailsSourceConfig.class).autowire();
|
||||
SecurityContextHolderAwareRequestFilter scaFilter = getFilter(SecurityContextHolderAwareRequestFilter.class);
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = getFieldValue(scaFilter,
|
||||
"authenticationDetailsSource");
|
||||
assertThat(authenticationDetailsSource).isEqualTo(SharedAuthenticationDetailsSourceConfig.ADS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenServletApiWithDefaultsInLambdaThenUsesDefaultRolePrefix() throws Exception {
|
||||
this.spring.register(ServletApiWithDefaultsInLambdaConfig.class, AdminController.class).autowire();
|
||||
|
@ -321,6 +331,22 @@ public class ServletApiConfigurerTests {
|
|||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SharedAuthenticationDetailsSourceConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static AuthenticationDetailsSource<HttpServletRequest, ?> ADS = spy(AuthenticationDetailsSource.class);
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) {
|
||||
// @formatter:off
|
||||
http
|
||||
.setSharedObject(AuthenticationDetailsSource.class, ADS);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class ServletApiWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
|
@ -42,6 +43,7 @@ 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.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
@ -79,6 +81,8 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
|||
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
@ -158,6 +162,18 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
|||
this.trustResolver = trustResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationDetailsSource} to be used. The default is
|
||||
* {@link WebAuthenticationDetailsSource}.
|
||||
* @param authenticationDetailsSource the {@link AuthenticationDetailsSource} to use.
|
||||
* Cannot be null.
|
||||
*/
|
||||
void setAuthenticationDetailsSource(
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
|
||||
Assert.notNull(authenticationDetailsSource, "authenticationDetailsSource cannot be null");
|
||||
this.authenticationDetailsSource = authenticationDetailsSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServletRequest create(HttpServletRequest request, HttpServletResponse response) {
|
||||
return new Servlet3SecurityContextHolderAwareRequestWrapper(request, this.rolePrefix, response);
|
||||
|
@ -233,7 +249,11 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
|||
private Authentication getAuthentication(AuthenticationManager authManager, String username, String password)
|
||||
throws ServletException {
|
||||
try {
|
||||
return authManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username,
|
||||
password);
|
||||
Object details = HttpServlet3RequestFactory.this.authenticationDetailsSource.buildDetails(this);
|
||||
authentication.setDetails(details);
|
||||
return authManager.authenticate(authentication);
|
||||
}
|
||||
catch (AuthenticationException ex) {
|
||||
SecurityContextHolder.clearContext();
|
||||
|
|
|
@ -27,12 +27,14 @@ import javax.servlet.ServletResponse;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
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.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
@ -80,6 +82,8 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
|
|||
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
public void setRolePrefix(String rolePrefix) {
|
||||
Assert.notNull(rolePrefix, "Role prefix must not be null");
|
||||
this.rolePrefix = rolePrefix;
|
||||
|
@ -172,9 +176,23 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
|
|||
updateFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationDetailsSource} to be used. The default is
|
||||
* {@link WebAuthenticationDetailsSource}.
|
||||
* @param authenticationDetailsSource the {@link AuthenticationDetailsSource} to use.
|
||||
* Cannot be null.
|
||||
*/
|
||||
public void setAuthenticationDetailsSource(
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
|
||||
Assert.notNull(authenticationDetailsSource, "authenticationDetailsSource cannot be null");
|
||||
this.authenticationDetailsSource = authenticationDetailsSource;
|
||||
updateFactory();
|
||||
}
|
||||
|
||||
private HttpServletRequestFactory createServlet3Factory(String rolePrefix) {
|
||||
HttpServlet3RequestFactory factory = new HttpServlet3RequestFactory(rolePrefix);
|
||||
factory.setTrustResolver(this.trustResolver);
|
||||
factory.setAuthenticationDetailsSource(this.authenticationDetailsSource);
|
||||
factory.setAuthenticationEntryPoint(this.authenticationEntryPoint);
|
||||
factory.setAuthenticationManager(this.authenticationManager);
|
||||
factory.setLogoutHandlers(this.logoutHandlers);
|
||||
|
|
Loading…
Reference in New Issue