Merge remote-tracking branch 'origin/5.8.x'
This commit is contained in:
@@ -18,6 +18,8 @@ package org.springframework.security.core.context;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -127,9 +129,9 @@ public final class ListeningSecurityContextHolderStrategy implements SecurityCon
|
||||
*/
|
||||
@Override
|
||||
public void clearContext() {
|
||||
SecurityContext from = getContext();
|
||||
Supplier<SecurityContext> deferred = this.delegate.getDeferredContext();
|
||||
this.delegate.clearContext();
|
||||
publish(from, null);
|
||||
publish(new SecurityContextChangedEvent(deferred, SecurityContextChangedEvent.NO_CONTEXT));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,14 +142,28 @@ public final class ListeningSecurityContextHolderStrategy implements SecurityCon
|
||||
return this.delegate.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Supplier<SecurityContext> getDeferredContext() {
|
||||
return this.delegate.getDeferredContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setContext(SecurityContext context) {
|
||||
SecurityContext from = getContext();
|
||||
this.delegate.setContext(context);
|
||||
publish(from, context);
|
||||
setDeferredContext(() -> context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setDeferredContext(Supplier<SecurityContext> deferredContext) {
|
||||
this.delegate.setDeferredContext(new PublishOnceSupplier(getDeferredContext(), deferredContext));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,14 +174,42 @@ public final class ListeningSecurityContextHolderStrategy implements SecurityCon
|
||||
return this.delegate.createEmptyContext();
|
||||
}
|
||||
|
||||
private void publish(SecurityContext previous, SecurityContext current) {
|
||||
if (previous == current) {
|
||||
return;
|
||||
}
|
||||
SecurityContextChangedEvent event = new SecurityContextChangedEvent(previous, current);
|
||||
private void publish(SecurityContextChangedEvent event) {
|
||||
for (SecurityContextChangedListener listener : this.listeners) {
|
||||
listener.securityContextChanged(event);
|
||||
}
|
||||
}
|
||||
|
||||
class PublishOnceSupplier implements Supplier<SecurityContext> {
|
||||
|
||||
private final AtomicBoolean isPublished = new AtomicBoolean(false);
|
||||
|
||||
private final Supplier<SecurityContext> old;
|
||||
|
||||
private final Supplier<SecurityContext> updated;
|
||||
|
||||
PublishOnceSupplier(Supplier<SecurityContext> old, Supplier<SecurityContext> updated) {
|
||||
if (old instanceof PublishOnceSupplier) {
|
||||
this.old = ((PublishOnceSupplier) old).updated;
|
||||
}
|
||||
else {
|
||||
this.old = old;
|
||||
}
|
||||
this.updated = updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityContext get() {
|
||||
SecurityContext updated = this.updated.get();
|
||||
if (this.isPublished.compareAndSet(false, true)) {
|
||||
SecurityContext old = this.old.get();
|
||||
if (old != updated) {
|
||||
publish(new SecurityContextChangedEvent(old, updated));
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.core.context;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
@@ -26,9 +28,24 @@ import org.springframework.context.ApplicationEvent;
|
||||
*/
|
||||
public class SecurityContextChangedEvent extends ApplicationEvent {
|
||||
|
||||
private final SecurityContext oldContext;
|
||||
public static final Supplier<SecurityContext> NO_CONTEXT = () -> null;
|
||||
|
||||
private final SecurityContext newContext;
|
||||
private final Supplier<SecurityContext> oldContext;
|
||||
|
||||
private final Supplier<SecurityContext> newContext;
|
||||
|
||||
/**
|
||||
* Construct an event
|
||||
* @param oldContext the old security context
|
||||
* @param newContext the new security context, use
|
||||
* {@link SecurityContextChangedEvent#NO_CONTEXT} for if the context is cleared
|
||||
* @since 5.8
|
||||
*/
|
||||
public SecurityContextChangedEvent(Supplier<SecurityContext> oldContext, Supplier<SecurityContext> newContext) {
|
||||
super(SecurityContextHolder.class);
|
||||
this.oldContext = oldContext;
|
||||
this.newContext = newContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an event
|
||||
@@ -36,9 +53,7 @@ public class SecurityContextChangedEvent extends ApplicationEvent {
|
||||
* @param newContext the new security context
|
||||
*/
|
||||
public SecurityContextChangedEvent(SecurityContext oldContext, SecurityContext newContext) {
|
||||
super(SecurityContextHolder.class);
|
||||
this.oldContext = oldContext;
|
||||
this.newContext = newContext;
|
||||
this(() -> oldContext, (newContext != null) ? () -> newContext : NO_CONTEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,7 +62,7 @@ public class SecurityContextChangedEvent extends ApplicationEvent {
|
||||
* @return the previous {@link SecurityContext}
|
||||
*/
|
||||
public SecurityContext getOldContext() {
|
||||
return this.oldContext;
|
||||
return this.oldContext.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +71,21 @@ public class SecurityContextChangedEvent extends ApplicationEvent {
|
||||
* @return the current {@link SecurityContext}
|
||||
*/
|
||||
public SecurityContext getNewContext() {
|
||||
return this.newContext;
|
||||
return this.newContext.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Say whether the event is a context-clearing event.
|
||||
*
|
||||
* <p>
|
||||
* This method is handy for avoiding looking up the new context to confirm it is a
|
||||
* cleared event.
|
||||
* @return {@code true} if the new context is
|
||||
* {@link SecurityContextChangedEvent#NO_CONTEXT}
|
||||
* @since 5.8
|
||||
*/
|
||||
public boolean isCleared() {
|
||||
return this.newContext == NO_CONTEXT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user