|
@@ -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");
|
|
|
* 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.SecurityContextHolder;
|
|
|
+import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
|
|
import org.springframework.util.Assert;
|
|
|
|
|
|
/**
|
|
@@ -40,10 +41,15 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
|
|
|
|
|
private final Callable<V> delegate;
|
|
|
|
|
|
+ private final boolean explicitSecurityContextProvided;
|
|
|
+
|
|
|
/**
|
|
|
* The {@link SecurityContext} that the delegate {@link Callable} will be ran as.
|
|
|
*/
|
|
|
- private final SecurityContext delegateSecurityContext;
|
|
|
+ private SecurityContext delegateSecurityContext;
|
|
|
+
|
|
|
+ private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
|
|
+ .getContextHolderStrategy();
|
|
|
|
|
|
/**
|
|
|
* The {@link SecurityContext} that was on the {@link SecurityContextHolder} prior to
|
|
@@ -60,10 +66,7 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
|
|
* {@link Callable}. Cannot be null.
|
|
|
*/
|
|
|
public DelegatingSecurityContextCallable(Callable<V> delegate, SecurityContext securityContext) {
|
|
|
- Assert.notNull(delegate, "delegate cannot be null");
|
|
|
- Assert.notNull(securityContext, "securityContext cannot be null");
|
|
|
- this.delegate = delegate;
|
|
|
- this.delegateSecurityContext = securityContext;
|
|
|
+ this(delegate, securityContext, true);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -73,28 +76,51 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
|
|
* {@link SecurityContext}. Cannot be null.
|
|
|
*/
|
|
|
public DelegatingSecurityContextCallable(Callable<V> delegate) {
|
|
|
- this(delegate, SecurityContextHolder.getContext());
|
|
|
+ this(delegate, SecurityContextHolder.getContext(), false);
|
|
|
+ }
|
|
|
+
|
|
|
+ private DelegatingSecurityContextCallable(Callable<V> delegate, SecurityContext securityContext,
|
|
|
+ boolean explicitSecurityContextProvided) {
|
|
|
+ Assert.notNull(delegate, "delegate cannot be null");
|
|
|
+ Assert.notNull(securityContext, "securityContext cannot be null");
|
|
|
+ this.delegate = delegate;
|
|
|
+ this.delegateSecurityContext = securityContext;
|
|
|
+ this.explicitSecurityContextProvided = explicitSecurityContextProvided;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public V call() throws Exception {
|
|
|
- this.originalSecurityContext = SecurityContextHolder.getContext();
|
|
|
+ this.originalSecurityContext = this.securityContextHolderStrategy.getContext();
|
|
|
try {
|
|
|
- SecurityContextHolder.setContext(this.delegateSecurityContext);
|
|
|
+ this.securityContextHolderStrategy.setContext(this.delegateSecurityContext);
|
|
|
return this.delegate.call();
|
|
|
}
|
|
|
finally {
|
|
|
- SecurityContext emptyContext = SecurityContextHolder.createEmptyContext();
|
|
|
+ SecurityContext emptyContext = this.securityContextHolderStrategy.createEmptyContext();
|
|
|
if (emptyContext.equals(this.originalSecurityContext)) {
|
|
|
- SecurityContextHolder.clearContext();
|
|
|
+ this.securityContextHolderStrategy.clearContext();
|
|
|
}
|
|
|
else {
|
|
|
- SecurityContextHolder.setContext(this.originalSecurityContext);
|
|
|
+ this.securityContextHolderStrategy.setContext(this.originalSecurityContext);
|
|
|
}
|
|
|
this.originalSecurityContext = null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 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;
|
|
|
+ if (!this.explicitSecurityContextProvided) {
|
|
|
+ this.delegateSecurityContext = securityContextHolderStrategy.getContext();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public String toString() {
|
|
|
return this.delegate.toString();
|
|
@@ -116,4 +142,15 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
|
|
: new DelegatingSecurityContextCallable<>(delegate);
|
|
|
}
|
|
|
|
|
|
+ static <V> Callable<V> create(Callable<V> delegate, SecurityContext securityContext,
|
|
|
+ SecurityContextHolderStrategy securityContextHolderStrategy) {
|
|
|
+ Assert.notNull(delegate, "delegate cannot be null");
|
|
|
+ Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
|
|
|
+ DelegatingSecurityContextCallable<V> callable = (securityContext != null)
|
|
|
+ ? new DelegatingSecurityContextCallable<>(delegate, securityContext)
|
|
|
+ : new DelegatingSecurityContextCallable<>(delegate);
|
|
|
+ callable.setSecurityContextHolderStrategy(securityContextHolderStrategy);
|
|
|
+ return callable;
|
|
|
+ }
|
|
|
+
|
|
|
}
|