Use SecurityContextHolderStrategy for Async Requests
Issue gh-11060 Issue gh-11061
This commit is contained in:
parent
5086409dcf
commit
a218d3e140
|
@ -33,6 +33,8 @@ import org.springframework.security.config.annotation.authentication.configurati
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||||
|
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
|
@ -58,6 +60,9 @@ class HttpSecurityConfiguration {
|
||||||
|
|
||||||
private ApplicationContext context;
|
private ApplicationContext context;
|
||||||
|
|
||||||
|
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||||
|
.getContextHolderStrategy();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||||
this.objectPostProcessor = objectPostProcessor;
|
this.objectPostProcessor = objectPostProcessor;
|
||||||
|
@ -77,6 +82,11 @@ class HttpSecurityConfiguration {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||||
|
this.securityContextHolderStrategy = securityContextHolderStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(HTTPSECURITY_BEAN_NAME)
|
@Bean(HTTPSECURITY_BEAN_NAME)
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
HttpSecurity httpSecurity() throws Exception {
|
HttpSecurity httpSecurity() throws Exception {
|
||||||
|
@ -86,10 +96,12 @@ class HttpSecurityConfiguration {
|
||||||
this.objectPostProcessor, passwordEncoder);
|
this.objectPostProcessor, passwordEncoder);
|
||||||
authenticationBuilder.parentAuthenticationManager(authenticationManager());
|
authenticationBuilder.parentAuthenticationManager(authenticationManager());
|
||||||
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
|
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
|
||||||
|
WebAsyncManagerIntegrationFilter webAsyncManagerIntegrationFilter = new WebAsyncManagerIntegrationFilter();
|
||||||
|
webAsyncManagerIntegrationFilter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.csrf(withDefaults())
|
.csrf(withDefaults())
|
||||||
.addFilter(new WebAsyncManagerIntegrationFilter())
|
.addFilter(webAsyncManagerIntegrationFilter)
|
||||||
.exceptionHandling(withDefaults())
|
.exceptionHandling(withDefaults())
|
||||||
.headers(withDefaults())
|
.headers(withDefaults())
|
||||||
.sessionManagement(withDefaults())
|
.sessionManagement(withDefaults())
|
||||||
|
|
|
@ -587,6 +587,7 @@ class HttpConfigurationBuilder {
|
||||||
boolean asyncSupported = ClassUtils.hasMethod(ServletRequest.class, "startAsync");
|
boolean asyncSupported = ClassUtils.hasMethod(ServletRequest.class, "startAsync");
|
||||||
if (asyncSupported) {
|
if (asyncSupported) {
|
||||||
this.webAsyncManagerFilter = new RootBeanDefinition(WebAsyncManagerIntegrationFilter.class);
|
this.webAsyncManagerFilter = new RootBeanDefinition(WebAsyncManagerIntegrationFilter.class);
|
||||||
|
this.webAsyncManagerFilter.getPropertyValues().add("securityContextHolderStrategy", this.holderStrategyRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,13 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
import org.springframework.mock.web.MockHttpSession;
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
@ -54,6 +56,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||||
|
@ -134,6 +138,22 @@ public class HttpSecurityConfigurationTests {
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void asyncDispatchWhenCustomSecurityContextHolderStrategyThenUses() throws Exception {
|
||||||
|
this.spring.register(DefaultWithFilterChainConfig.class, SecurityContextChangedListenerConfig.class,
|
||||||
|
NameController.class).autowire();
|
||||||
|
// @formatter:off
|
||||||
|
MockHttpServletRequestBuilder requestWithBob = get("/name").with(user("Bob"));
|
||||||
|
MvcResult mvcResult = this.mockMvc.perform(requestWithBob)
|
||||||
|
.andExpect(request().asyncStarted())
|
||||||
|
.andReturn();
|
||||||
|
this.mockMvc.perform(asyncDispatch(mvcResult))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().string("Bob"));
|
||||||
|
// @formatter:on
|
||||||
|
verify(this.spring.getContext().getBean(SecurityContextHolderStrategy.class), atLeastOnce()).getContext();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getWhenDefaultFilterChainBeanThenAnonymousPermitted() throws Exception {
|
public void getWhenDefaultFilterChainBeanThenAnonymousPermitted() throws Exception {
|
||||||
this.spring.register(AuthorizeRequestsConfig.class, UserDetailsConfig.class, BaseController.class).autowire();
|
this.spring.register(AuthorizeRequestsConfig.class, UserDetailsConfig.class, BaseController.class).autowire();
|
||||||
|
@ -243,8 +263,8 @@ public class HttpSecurityConfigurationTests {
|
||||||
static class NameController {
|
static class NameController {
|
||||||
|
|
||||||
@GetMapping("/name")
|
@GetMapping("/name")
|
||||||
Callable<String> name() {
|
Callable<String> name(Authentication authentication) {
|
||||||
return () -> SecurityContextHolder.getContext().getAuthentication().getName();
|
return () -> authentication.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
import javax.security.auth.Subject;
|
||||||
|
@ -127,12 +128,15 @@ import static org.mockito.Mockito.verify;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
||||||
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.x509;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.x509;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -762,6 +766,21 @@ public class MiscHttpConfigTests {
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void asyncDispatchWhenCustomSecurityContextHolderStrategyThenUses() throws Exception {
|
||||||
|
this.spring.configLocations(xml("WithSecurityContextHolderStrategy")).autowire();
|
||||||
|
// @formatter:off
|
||||||
|
MockHttpServletRequestBuilder requestWithBob = get("/name").with(user("Bob"));
|
||||||
|
MvcResult mvcResult = this.mvc.perform(requestWithBob)
|
||||||
|
.andExpect(request().asyncStarted())
|
||||||
|
.andReturn();
|
||||||
|
this.mvc.perform(asyncDispatch(mvcResult))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().string("Bob"));
|
||||||
|
// @formatter:on
|
||||||
|
verify(this.spring.getContext().getBean(SecurityContextHolderStrategy.class), atLeastOnce()).getContext();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SEC-1893
|
* SEC-1893
|
||||||
*/
|
*/
|
||||||
|
@ -905,6 +924,11 @@ public class MiscHttpConfigTests {
|
||||||
return authentication.getDetails().getClass().getName();
|
return authentication.getDetails().getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/name")
|
||||||
|
Callable<String> name(Authentication authentication) {
|
||||||
|
return () -> authentication.getName();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright 2002-2018 the original author or authors.
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/security
|
||||||
|
https://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans
|
||||||
|
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/mvc
|
||||||
|
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||||
|
|
||||||
|
<http auto-config="true" security-context-holder-strategy-ref="ref">
|
||||||
|
<intercept-url pattern="/**" access="authenticated"/>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean id="ref" class="org.mockito.Mockito" factory-method="spy">
|
||||||
|
<b:constructor-arg>
|
||||||
|
<b:bean class="org.springframework.security.config.MockSecurityContextHolderStrategy"/>
|
||||||
|
</b:constructor-arg>
|
||||||
|
</b:bean>
|
||||||
|
|
||||||
|
<mvc:annotation-driven>
|
||||||
|
<mvc:argument-resolvers>
|
||||||
|
<b:bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver">
|
||||||
|
<b:property name="securityContextHolderStrategy" ref="ref"/>
|
||||||
|
</b:bean>
|
||||||
|
</mvc:argument-resolvers>
|
||||||
|
</mvc:annotation-driven>
|
||||||
|
|
||||||
|
<b:bean class="org.springframework.security.config.http.MiscHttpConfigTests.AuthenticationController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -20,6 +20,7 @@ import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.context.request.NativeWebRequest;
|
import org.springframework.web.context.request.NativeWebRequest;
|
||||||
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
|
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
|
||||||
|
@ -43,6 +44,9 @@ public final class SecurityContextCallableProcessingInterceptor implements Calla
|
||||||
|
|
||||||
private volatile SecurityContext securityContext;
|
private volatile SecurityContext securityContext;
|
||||||
|
|
||||||
|
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||||
|
.getContextHolderStrategy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link SecurityContextCallableProcessingInterceptor} that uses the
|
* Create a new {@link SecurityContextCallableProcessingInterceptor} that uses the
|
||||||
* {@link SecurityContext} from the {@link SecurityContextHolder} at the time
|
* {@link SecurityContext} from the {@link SecurityContextHolder} at the time
|
||||||
|
@ -67,18 +71,29 @@ public final class SecurityContextCallableProcessingInterceptor implements Calla
|
||||||
@Override
|
@Override
|
||||||
public <T> void beforeConcurrentHandling(NativeWebRequest request, Callable<T> task) {
|
public <T> void beforeConcurrentHandling(NativeWebRequest request, Callable<T> task) {
|
||||||
if (this.securityContext == null) {
|
if (this.securityContext == null) {
|
||||||
setSecurityContext(SecurityContextHolder.getContext());
|
setSecurityContext(this.securityContextHolderStrategy.getContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
|
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
|
||||||
SecurityContextHolder.setContext(this.securityContext);
|
this.securityContextHolderStrategy.setContext(this.securityContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
|
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
|
||||||
SecurityContextHolder.clearContext();
|
this.securityContextHolderStrategy.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
|
||||||
|
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
|
||||||
|
*
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||||
|
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
|
||||||
|
this.securityContextHolderStrategy = securityContextHolderStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSecurityContext(SecurityContext securityContext) {
|
private void setSecurityContext(SecurityContext securityContext) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,6 +25,9 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.context.request.async.WebAsyncManager;
|
import org.springframework.web.context.request.async.WebAsyncManager;
|
||||||
import org.springframework.web.context.request.async.WebAsyncUtils;
|
import org.springframework.web.context.request.async.WebAsyncUtils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
@ -42,6 +45,9 @@ public final class WebAsyncManagerIntegrationFilter extends OncePerRequestFilter
|
||||||
|
|
||||||
private static final Object CALLABLE_INTERCEPTOR_KEY = new Object();
|
private static final Object CALLABLE_INTERCEPTOR_KEY = new Object();
|
||||||
|
|
||||||
|
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||||
|
.getContextHolderStrategy();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
@ -49,10 +55,22 @@ public final class WebAsyncManagerIntegrationFilter extends OncePerRequestFilter
|
||||||
SecurityContextCallableProcessingInterceptor securityProcessingInterceptor = (SecurityContextCallableProcessingInterceptor) asyncManager
|
SecurityContextCallableProcessingInterceptor securityProcessingInterceptor = (SecurityContextCallableProcessingInterceptor) asyncManager
|
||||||
.getCallableInterceptor(CALLABLE_INTERCEPTOR_KEY);
|
.getCallableInterceptor(CALLABLE_INTERCEPTOR_KEY);
|
||||||
if (securityProcessingInterceptor == null) {
|
if (securityProcessingInterceptor == null) {
|
||||||
asyncManager.registerCallableInterceptor(CALLABLE_INTERCEPTOR_KEY,
|
SecurityContextCallableProcessingInterceptor interceptor = new SecurityContextCallableProcessingInterceptor();
|
||||||
new SecurityContextCallableProcessingInterceptor());
|
interceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
|
||||||
|
asyncManager.registerCallableInterceptor(CALLABLE_INTERCEPTOR_KEY, interceptor);
|
||||||
}
|
}
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
|
||||||
|
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
|
||||||
|
*
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||||
|
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
|
||||||
|
this.securityContextHolderStrategy = securityContextHolderStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue