Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit 9fdc0aa

Browse files
committed
fix(#632): propagate spring security context
Propagate the Spring Security context if on the class path. fix #632
1 parent ca66b31 commit 9fdc0aa

File tree

6 files changed

+80
-3
lines changed

6 files changed

+80
-3
lines changed

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ TARGET_COMPATIBILITY=1.8
3333
LIB_GRAPHQL_JAVA_VER=16.2
3434
LIB_EXTENDED_SCALARS_VER=16.0.1
3535
LIB_SPRING_BOOT_VER=2.4.5
36-
LIB_GRAPHQL_SERVLET_VER=11.1.1
36+
LIB_GRAPHQL_SERVLET_VER=11.2.0-SNAPSHOT
3737
LIB_GRAPHQL_JAVA_TOOLS_VER=11.0.1
3838
LIB_GRAPHQL_ANNOTATIONS_VER=8.3
3939
LIB_REFLECTIONS_VER=0.9.11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package graphql.kickstart.autoconfigure.web.servlet;
2+
3+
import lombok.Data;
4+
import org.springframework.boot.context.properties.ConfigurationProperties;
5+
6+
@Data
7+
@ConfigurationProperties(prefix = "graphql.servlet.async")
8+
public class AsyncServletProperties {
9+
10+
private boolean enabled = true;
11+
private long timeout = 30000;
12+
private Threads threads = new Threads();
13+
14+
@Data
15+
static class Threads {
16+
private int min = 10;
17+
private int max = 200;
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package graphql.kickstart.autoconfigure.web.servlet;
2+
3+
import graphql.kickstart.servlet.AsyncTaskDecorator;
4+
import org.springframework.security.core.context.SecurityContext;
5+
import org.springframework.security.core.context.SecurityContextHolder;
6+
7+
class DelegatingSecurityContextAsyncTaskDecorator implements AsyncTaskDecorator {
8+
9+
@Override
10+
public Runnable decorate(Runnable runnable) {
11+
SecurityContext delegateSecurityContext = SecurityContextHolder.getContext();
12+
return () -> {
13+
SecurityContext originalSecurityContext = SecurityContextHolder.getContext();
14+
try {
15+
SecurityContextHolder.setContext(delegateSecurityContext);
16+
runnable.run();
17+
} finally {
18+
SecurityContext emptyContext = SecurityContextHolder.createEmptyContext();
19+
if (emptyContext.equals(originalSecurityContext)) {
20+
SecurityContextHolder.clearContext();
21+
} else {
22+
SecurityContextHolder.setContext(originalSecurityContext);
23+
}
24+
}
25+
};
26+
}
27+
}

graphql-spring-boot-autoconfigure/src/main/java/graphql/kickstart/autoconfigure/web/servlet/GraphQLWebAutoConfiguration.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import graphql.kickstart.execution.config.ObjectMapperProvider;
4444
import graphql.kickstart.execution.error.GraphQLErrorHandler;
4545
import graphql.kickstart.servlet.AbstractGraphQLHttpServlet;
46+
import graphql.kickstart.servlet.AsyncTaskDecorator;
4647
import graphql.kickstart.servlet.GraphQLConfiguration;
4748
import graphql.kickstart.servlet.GraphQLHttpServlet;
4849
import graphql.kickstart.servlet.cache.GraphQLResponseCacheManager;
@@ -61,6 +62,7 @@
6162
import java.util.List;
6263
import java.util.Map;
6364
import java.util.Map.Entry;
65+
import java.util.concurrent.Executor;
6466
import javax.servlet.MultipartConfigElement;
6567
import lombok.RequiredArgsConstructor;
6668
import lombok.extern.slf4j.Slf4j;
@@ -101,14 +103,15 @@
101103
havingValue = "true",
102104
matchIfMissing = true)
103105
@AutoConfigureAfter({GraphQLJavaToolsAutoConfiguration.class, JacksonAutoConfiguration.class})
104-
@EnableConfigurationProperties({GraphQLServletProperties.class})
106+
@EnableConfigurationProperties({GraphQLServletProperties.class, AsyncServletProperties.class})
105107
public class GraphQLWebAutoConfiguration {
106108

107109
public static final String QUERY_EXECUTION_STRATEGY = "queryExecutionStrategy";
108110
public static final String MUTATION_EXECUTION_STRATEGY = "mutationExecutionStrategy";
109111
public static final String SUBSCRIPTION_EXECUTION_STRATEGY = "subscriptionExecutionStrategy";
110112

111113
private final GraphQLServletProperties graphQLServletProperties;
114+
private final AsyncServletProperties asyncServletProperties;
112115
private final ErrorHandlerSupplier errorHandlerSupplier = new ErrorHandlerSupplier(null);
113116

114117
@Bean
@@ -293,7 +296,9 @@ public GraphQLConfiguration graphQLServletConfiguration(
293296
GraphQLObjectMapper graphQLObjectMapper,
294297
@Autowired(required = false) List<GraphQLServletListener> listeners,
295298
@Autowired(required = false) BatchInputPreProcessor batchInputPreProcessor,
296-
@Autowired(required = false) GraphQLResponseCacheManager responseCacheManager) {
299+
@Autowired(required = false) GraphQLResponseCacheManager responseCacheManager,
300+
@Autowired(required = false) AsyncTaskDecorator asyncTaskDecorator,
301+
@Autowired(required = false) Executor asyncExecutor) {
297302
return GraphQLConfiguration.with(invocationInputFactory)
298303
.with(graphQLInvoker)
299304
.with(graphQLObjectMapper)
@@ -303,6 +308,10 @@ public GraphQLConfiguration graphQLServletConfiguration(
303308
.with(graphQLServletProperties.getContextSetting())
304309
.with(responseCacheManager)
305310
.asyncTimeout(graphQLServletProperties.getAsyncTimeout())
311+
.with(asyncTaskDecorator)
312+
.asyncCorePoolSize(asyncServletProperties.getThreads().getMin())
313+
.asyncCorePoolSize(asyncServletProperties.getThreads().getMax())
314+
.with(asyncExecutor)
306315
.build();
307316
}
308317

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package graphql.kickstart.autoconfigure.web.servlet;
2+
3+
import graphql.kickstart.servlet.AsyncTaskDecorator;
4+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
6+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
7+
import org.springframework.context.annotation.Bean;
8+
import org.springframework.context.annotation.Configuration;
9+
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
10+
11+
@Configuration
12+
@AutoConfigureBefore(GraphQLWebAutoConfiguration.class)
13+
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
14+
public class GraphQLWebSecurityAutoConfiguration {
15+
16+
@Bean
17+
@ConditionalOnMissingBean
18+
public AsyncTaskDecorator delegatingSecurityContextAsyncTaskDecorator() {
19+
return new DelegatingSecurityContextAsyncTaskDecorator();
20+
}
21+
}

graphql-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ org.springframework.context.ApplicationContextInitializer=\
22
graphql.kickstart.autoconfigure.web.servlet.GraphQLExtendedScalarsInitializer
33
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
44
graphql.kickstart.autoconfigure.web.servlet.GraphQLWebAutoConfiguration,\
5+
graphql.kickstart.autoconfigure.web.servlet.GraphQLWebSecurityAutoConfiguration,\
56
graphql.kickstart.autoconfigure.web.servlet.GraphQLWebsocketAutoConfiguration,\
67
graphql.kickstart.autoconfigure.web.servlet.GraphQLInstrumentationAutoConfiguration,\
78
graphql.kickstart.autoconfigure.web.reactive.GraphQLSpringWebfluxAutoConfiguration,\

0 commit comments

Comments
 (0)