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

Commit b442a52

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

File tree

6 files changed

+96
-38
lines changed

6 files changed

+96
-38
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ public class AsyncServletProperties {
1515
static class Threads {
1616
private int min = 10;
1717
private int max = 200;
18+
private String namePrefix = "graphql-exec-";
1819
}
1920
}

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

-27
This file was deleted.

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ public class GraphQLServletProperties {
3333
private boolean exceptionHandlersEnabled = false;
3434
private long subscriptionTimeout = 0;
3535
private ContextSetting contextSetting = ContextSetting.PER_QUERY_WITH_INSTRUMENTATION;
36-
private long asyncTimeout = 30000;
37-
private boolean asyncModeEnabled = true;
36+
/** @deprecated Use <tt>graphql.servlet.async.timeout</tt> instead */
37+
@Deprecated private Long asyncTimeout;
38+
/** @deprecated Use <tt>graphql.servlet.async.enabled</tt> instead */
39+
@Deprecated private Boolean asyncModeEnabled;
40+
3841
private String tracingEnabled = "false";
3942
private boolean actuatorMetrics;
4043
private Integer maxQueryComplexity;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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("graphql.spring.security")
8+
public class GraphQLSpringSecurityProperties {
9+
10+
private boolean delegateSecurityContext = true;
11+
}

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

+33-3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import lombok.extern.slf4j.Slf4j;
6969
import org.springframework.beans.factory.ObjectProvider;
7070
import org.springframework.beans.factory.annotation.Autowired;
71+
import org.springframework.beans.factory.annotation.Qualifier;
7172
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
7273
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
7374
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -83,6 +84,7 @@
8384
import org.springframework.context.annotation.Configuration;
8485
import org.springframework.context.annotation.Import;
8586
import org.springframework.http.HttpMethod;
87+
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
8688
import org.springframework.web.cors.CorsConfiguration;
8789
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
8890
import org.springframework.web.filter.CorsFilter;
@@ -298,7 +300,11 @@ public GraphQLConfiguration graphQLServletConfiguration(
298300
@Autowired(required = false) BatchInputPreProcessor batchInputPreProcessor,
299301
@Autowired(required = false) GraphQLResponseCacheManager responseCacheManager,
300302
@Autowired(required = false) AsyncTaskDecorator asyncTaskDecorator,
301-
@Autowired(required = false) Executor asyncExecutor) {
303+
@Autowired(required = false) @Qualifier("graphqlAsyncTaskExecutor") Executor asyncExecutor) {
304+
long asyncTimeout =
305+
graphQLServletProperties.getAsyncTimeout() != null
306+
? graphQLServletProperties.getAsyncTimeout()
307+
: asyncServletProperties.getTimeout();
302308
return GraphQLConfiguration.with(invocationInputFactory)
303309
.with(graphQLInvoker)
304310
.with(graphQLObjectMapper)
@@ -307,14 +313,34 @@ public GraphQLConfiguration graphQLServletConfiguration(
307313
.with(batchInputPreProcessor)
308314
.with(graphQLServletProperties.getContextSetting())
309315
.with(responseCacheManager)
310-
.asyncTimeout(graphQLServletProperties.getAsyncTimeout())
316+
.asyncTimeout(asyncTimeout)
311317
.with(asyncTaskDecorator)
312318
.asyncCorePoolSize(asyncServletProperties.getThreads().getMin())
313319
.asyncCorePoolSize(asyncServletProperties.getThreads().getMax())
314320
.with(asyncExecutor)
315321
.build();
316322
}
317323

324+
@Bean("graphqlAsyncTaskExecutor")
325+
@ConditionalOnMissingBean(name = "graphqlAsyncTaskExecutor")
326+
public Executor threadPoolTaskExecutor() {
327+
if (isAsyncModeEnabled()) {
328+
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
329+
executor.setCorePoolSize(asyncServletProperties.getThreads().getMin());
330+
executor.setMaxPoolSize(asyncServletProperties.getThreads().getMax());
331+
executor.setThreadNamePrefix(asyncServletProperties.getThreads().getNamePrefix());
332+
executor.initialize();
333+
return executor;
334+
}
335+
return null;
336+
}
337+
338+
private boolean isAsyncModeEnabled() {
339+
return graphQLServletProperties.getAsyncModeEnabled() != null
340+
? graphQLServletProperties.getAsyncModeEnabled()
341+
: asyncServletProperties.isEnabled();
342+
}
343+
318344
@Bean
319345
@ConditionalOnMissingBean
320346
public GraphQLHttpServlet graphQLHttpServlet(GraphQLConfiguration graphQLConfiguration) {
@@ -332,7 +358,11 @@ public ServletRegistrationBean<AbstractGraphQLHttpServlet> graphQLServletRegistr
332358
} else {
333359
registration.setMultipartConfig(new MultipartConfigElement(""));
334360
}
335-
registration.setAsyncSupported(graphQLServletProperties.isAsyncModeEnabled());
361+
if (graphQLServletProperties.getAsyncModeEnabled() != null) {
362+
registration.setAsyncSupported(graphQLServletProperties.getAsyncModeEnabled());
363+
} else {
364+
registration.setAsyncSupported(asyncServletProperties.isEnabled());
365+
}
336366
return registration;
337367
}
338368
}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,61 @@
11
package graphql.kickstart.autoconfigure.web.servlet;
22

3-
import graphql.kickstart.servlet.AsyncTaskDecorator;
3+
import graphql.kickstart.autoconfigure.web.OnSchemaOrSchemaProviderBean;
4+
import java.util.concurrent.Executor;
5+
import lombok.RequiredArgsConstructor;
46
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
57
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
68
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
9+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
10+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
11+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
12+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
713
import org.springframework.context.annotation.Bean;
14+
import org.springframework.context.annotation.Conditional;
815
import org.springframework.context.annotation.Configuration;
16+
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
917
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
18+
import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor;
19+
import org.springframework.web.servlet.DispatcherServlet;
1020

1121
@Configuration
22+
@RequiredArgsConstructor
23+
@ConditionalOnWebApplication(type = Type.SERVLET)
24+
@Conditional(OnSchemaOrSchemaProviderBean.class)
25+
@ConditionalOnProperty(
26+
value = "graphql.servlet.enabled",
27+
havingValue = "true",
28+
matchIfMissing = true)
1229
@AutoConfigureBefore(GraphQLWebAutoConfiguration.class)
13-
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
30+
@ConditionalOnClass({DispatcherServlet.class, DefaultAuthenticationEventPublisher.class})
31+
@EnableConfigurationProperties({
32+
GraphQLServletProperties.class,
33+
AsyncServletProperties.class,
34+
GraphQLSpringSecurityProperties.class
35+
})
1436
public class GraphQLWebSecurityAutoConfiguration {
1537

16-
@Bean
17-
@ConditionalOnMissingBean
18-
public AsyncTaskDecorator delegatingSecurityContextAsyncTaskDecorator() {
19-
return new DelegatingSecurityContextAsyncTaskDecorator();
38+
private final GraphQLServletProperties graphqlServletProperties;
39+
private final AsyncServletProperties asyncServletProperties;
40+
private final GraphQLSpringSecurityProperties securityProperties;
41+
42+
@Bean("graphqlAsyncTaskExecutor")
43+
@ConditionalOnMissingBean(name = "graphqlAsyncTaskExecutor")
44+
public Executor threadPoolTaskExecutor() {
45+
if (isAsyncModeEnabled() && securityProperties.isDelegateSecurityContext()) {
46+
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
47+
executor.setCorePoolSize(asyncServletProperties.getThreads().getMin());
48+
executor.setMaxPoolSize(asyncServletProperties.getThreads().getMax());
49+
executor.setThreadNamePrefix(asyncServletProperties.getThreads().getNamePrefix());
50+
executor.initialize();
51+
return new DelegatingSecurityContextAsyncTaskExecutor(executor);
52+
}
53+
return null;
54+
}
55+
56+
private boolean isAsyncModeEnabled() {
57+
return graphqlServletProperties.getAsyncModeEnabled() != null
58+
? graphqlServletProperties.getAsyncModeEnabled()
59+
: asyncServletProperties.isEnabled();
2060
}
2161
}

0 commit comments

Comments
 (0)