|
@@ -25,10 +25,8 @@ import org.springframework.util.Assert;
|
|
|
* then removing the {@link SecurityContext} after the delegate has completed.
|
|
|
* </p>
|
|
|
* <p>
|
|
|
- * By default the {@link SecurityContext} is only setup if {@link #call()} is
|
|
|
- * invoked on a separate {@link Thread} than the
|
|
|
- * {@link DelegatingSecurityContextCallable} was created on. This can be
|
|
|
- * overridden by setting {@link #setEnableOnOriginalThread(boolean)} to true.
|
|
|
+ * If there is a {@link SecurityContext} that already exists, it will be
|
|
|
+ * restored after the {@link #call()} method is invoked.
|
|
|
* </p>
|
|
|
*
|
|
|
* @author Rob Winch
|
|
@@ -38,11 +36,18 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
|
|
|
|
|
private final Callable<V> delegate;
|
|
|
|
|
|
- private final SecurityContext securityContext;
|
|
|
|
|
|
- private final Thread originalThread;
|
|
|
+ /**
|
|
|
+ * The {@link SecurityContext} that the delegate {@link Callable} will be
|
|
|
+ * ran as.
|
|
|
+ */
|
|
|
+ private final SecurityContext delegateSecurityContext;
|
|
|
|
|
|
- private boolean enableOnOriginalThread;
|
|
|
+ /**
|
|
|
+ * The {@link SecurityContext} that was on the {@link SecurityContextHolder}
|
|
|
+ * prior to being set to the delegateSecurityContext.
|
|
|
+ */
|
|
|
+ private SecurityContext originalSecurityContext;
|
|
|
|
|
|
/**
|
|
|
* Creates a new {@link DelegatingSecurityContextCallable} with a specific
|
|
@@ -57,8 +62,7 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
|
|
Assert.notNull(delegate, "delegate cannot be null");
|
|
|
Assert.notNull(securityContext, "securityContext cannot be null");
|
|
|
this.delegate = delegate;
|
|
|
- this.securityContext = securityContext;
|
|
|
- this.originalThread = Thread.currentThread();
|
|
|
+ this.delegateSecurityContext = securityContext;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -71,33 +75,21 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
|
|
this(delegate, SecurityContextHolder.getContext());
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Determines if the SecurityContext should be transfered if {@link #call()}
|
|
|
- * is invoked on the same {@link Thread} the
|
|
|
- * {@link DelegatingSecurityContextCallable} was created on.
|
|
|
- *
|
|
|
- * @param enableOnOriginalThread
|
|
|
- * if false (default), will only transfer the
|
|
|
- * {@link SecurityContext} if {@link #call()} is invoked on a
|
|
|
- * different {@link Thread} than the
|
|
|
- * {@link DelegatingSecurityContextCallable} was created on.
|
|
|
- *
|
|
|
- * @since 4.0.2
|
|
|
- */
|
|
|
- public void setEnableOnOriginalThread(boolean enableOnOriginalThread) {
|
|
|
- this.enableOnOriginalThread = enableOnOriginalThread;
|
|
|
- }
|
|
|
-
|
|
|
public V call() throws Exception {
|
|
|
- if(!enableOnOriginalThread && originalThread == Thread.currentThread()) {
|
|
|
- return delegate.call();
|
|
|
- }
|
|
|
+ this.originalSecurityContext = SecurityContextHolder.getContext();
|
|
|
+
|
|
|
try {
|
|
|
- SecurityContextHolder.setContext(securityContext);
|
|
|
+ SecurityContextHolder.setContext(delegateSecurityContext);
|
|
|
return delegate.call();
|
|
|
}
|
|
|
finally {
|
|
|
- SecurityContextHolder.clearContext();
|
|
|
+ SecurityContext emptyContext = SecurityContextHolder.createEmptyContext();
|
|
|
+ if(emptyContext.equals(originalSecurityContext)) {
|
|
|
+ SecurityContextHolder.clearContext();
|
|
|
+ } else {
|
|
|
+ SecurityContextHolder.setContext(originalSecurityContext);
|
|
|
+ }
|
|
|
+ this.originalSecurityContext = null;
|
|
|
}
|
|
|
}
|
|
|
|