Polish Authorization Event Support
- Added spring-security-config support - Renamed classes - Changed contracts to include the authenticated user and secured object - Added method security support Issue gh-9288
This commit is contained in:
+25
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,14 +16,34 @@
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
|
||||
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* A contract for publishing authorization events
|
||||
*
|
||||
* @author Parikshit Dutta
|
||||
* @since 5.5
|
||||
* @author Josh Cummings
|
||||
* @since 5.7
|
||||
* @see AuthorizationManager
|
||||
*/
|
||||
public interface AuthorizationEventPublisher {
|
||||
|
||||
void publishAuthorizationSuccess(AuthorizationDecision authorizationDecision);
|
||||
|
||||
void publishAuthorizationFailure(AuthorizationDecision authorizationDecision);
|
||||
/**
|
||||
* Publish the given details in the form of an event, typically
|
||||
* {@link AuthorizationGrantedEvent} or {@link AuthorizationDeniedEvent}.
|
||||
*
|
||||
* Note that success events can be very noisy if enabled by default. Because of this
|
||||
* implementations may choose to drop success events by default.
|
||||
* @param authentication a {@link Supplier} for the current user
|
||||
* @param object the secured object
|
||||
* @param decision the decision about whether the user may access the secured object
|
||||
* @param <T> the secured object's type
|
||||
*/
|
||||
<T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
|
||||
AuthorizationDecision decision);
|
||||
|
||||
}
|
||||
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.security.authorization.event.AuthorizationFailureEvent;
|
||||
import org.springframework.security.authorization.event.AuthorizationSuccessEvent;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link AuthorizationEventPublisher}
|
||||
*
|
||||
* @author Parikshit Dutta
|
||||
* @since 5.5
|
||||
*/
|
||||
public class DefaultAuthorizationEventPublisher implements AuthorizationEventPublisher, ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
public DefaultAuthorizationEventPublisher() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public DefaultAuthorizationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishAuthorizationSuccess(AuthorizationDecision authorizationDecision) {
|
||||
if (this.applicationEventPublisher != null) {
|
||||
this.applicationEventPublisher.publishEvent(new AuthorizationSuccessEvent(authorizationDecision));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishAuthorizationFailure(AuthorizationDecision authorizationDecision) {
|
||||
if (this.applicationEventPublisher != null) {
|
||||
this.applicationEventPublisher.publishEvent(new AuthorizationFailureEvent(authorizationDecision));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
|
||||
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An implementation of {@link AuthorizationEventPublisher} that uses Spring's event
|
||||
* publishing support.
|
||||
*
|
||||
* Because {@link AuthorizationGrantedEvent}s typically require additional business logic
|
||||
* to decide whether to publish, this implementation only publishes
|
||||
* {@link AuthorizationDeniedEvent}s.
|
||||
*
|
||||
* @author Parikshit Dutta
|
||||
* @author Josh Cummings
|
||||
* @since 5.7
|
||||
*/
|
||||
public final class SpringAuthorizationEventPublisher implements AuthorizationEventPublisher {
|
||||
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
/**
|
||||
* Construct this publisher using Spring's {@link ApplicationEventPublisher}
|
||||
* @param eventPublisher
|
||||
*/
|
||||
public SpringAuthorizationEventPublisher(ApplicationEventPublisher eventPublisher) {
|
||||
Assert.notNull(eventPublisher, "eventPublisher cannot be null");
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
|
||||
AuthorizationDecision decision) {
|
||||
if (decision == null || decision.isGranted()) {
|
||||
return;
|
||||
}
|
||||
AuthorizationDeniedEvent<T> failure = new AuthorizationDeniedEvent<>(authentication, object, decision);
|
||||
this.eventPublisher.publishEvent(failure);
|
||||
}
|
||||
|
||||
}
|
||||
+23
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,19 +16,37 @@
|
||||
|
||||
package org.springframework.security.authorization.event;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* An {@link ApplicationEvent} which indicates failed authorization.
|
||||
*
|
||||
* @author Parikshit Dutta
|
||||
* @since 5.5
|
||||
* @author Josh Cummings
|
||||
* @since 5.7
|
||||
*/
|
||||
public class AuthorizationFailureEvent extends ApplicationEvent {
|
||||
public class AuthorizationDeniedEvent<T> extends ApplicationEvent {
|
||||
|
||||
public AuthorizationFailureEvent(AuthorizationDecision authorizationDecision) {
|
||||
super(authorizationDecision);
|
||||
private final Supplier<Authentication> authentication;
|
||||
|
||||
private final AuthorizationDecision decision;
|
||||
|
||||
public AuthorizationDeniedEvent(Supplier<Authentication> authentication, T object, AuthorizationDecision decision) {
|
||||
super(object);
|
||||
this.authentication = authentication;
|
||||
this.decision = decision;
|
||||
}
|
||||
|
||||
public Supplier<Authentication> getAuthentication() {
|
||||
return this.authentication;
|
||||
}
|
||||
|
||||
public AuthorizationDecision getAuthorizationDecision() {
|
||||
return this.decision;
|
||||
}
|
||||
|
||||
}
|
||||
+26
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,19 +16,40 @@
|
||||
|
||||
package org.springframework.security.authorization.event;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link ApplicationEvent} which indicates successful authorization.
|
||||
*
|
||||
* @author Parikshit Dutta
|
||||
* @since 5.5
|
||||
* @author Josh Cummings
|
||||
* @since 5.7
|
||||
*/
|
||||
public class AuthorizationSuccessEvent extends ApplicationEvent {
|
||||
public class AuthorizationGrantedEvent<T> extends ApplicationEvent {
|
||||
|
||||
public AuthorizationSuccessEvent(AuthorizationDecision authorizationDecision) {
|
||||
super(authorizationDecision);
|
||||
private final Supplier<Authentication> authentication;
|
||||
|
||||
private final AuthorizationDecision decision;
|
||||
|
||||
public AuthorizationGrantedEvent(Supplier<Authentication> authentication, T object,
|
||||
AuthorizationDecision decision) {
|
||||
super(object);
|
||||
Assert.notNull(authentication, "authentication supplier cannot be null");
|
||||
this.authentication = authentication;
|
||||
this.decision = decision;
|
||||
}
|
||||
|
||||
public Supplier<Authentication> getAuthentication() {
|
||||
return this.authentication;
|
||||
}
|
||||
|
||||
public AuthorizationDecision getAuthorizationDecision() {
|
||||
return this.decision;
|
||||
}
|
||||
|
||||
}
|
||||
+23
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -33,6 +33,7 @@ import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -66,6 +67,8 @@ public final class AuthorizationManagerAfterMethodInterceptor
|
||||
|
||||
private int order;
|
||||
|
||||
private AuthorizationEventPublisher eventPublisher = AuthorizationManagerAfterMethodInterceptor::noPublish;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
* @param pointcut the {@link Pointcut} to use
|
||||
@@ -122,6 +125,17 @@ public final class AuthorizationManagerAfterMethodInterceptor
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this {@link AuthorizationEventPublisher} to publish the
|
||||
* {@link AuthorizationManager} result.
|
||||
* @param eventPublisher
|
||||
* @since 5.7
|
||||
*/
|
||||
public void setAuthorizationEventPublisher(AuthorizationEventPublisher eventPublisher) {
|
||||
Assert.notNull(eventPublisher, "eventPublisher cannot be null");
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -142,8 +156,9 @@ public final class AuthorizationManagerAfterMethodInterceptor
|
||||
|
||||
private void attemptAuthorization(MethodInvocation mi, Object result) {
|
||||
this.logger.debug(LogMessage.of(() -> "Authorizing method invocation " + mi));
|
||||
AuthorizationDecision decision = this.authorizationManager.check(AUTHENTICATION_SUPPLIER,
|
||||
new MethodInvocationResult(mi, result));
|
||||
MethodInvocationResult object = new MethodInvocationResult(mi, result);
|
||||
AuthorizationDecision decision = this.authorizationManager.check(AUTHENTICATION_SUPPLIER, object);
|
||||
this.eventPublisher.publishAuthorizationEvent(AUTHENTICATION_SUPPLIER, object, decision);
|
||||
if (decision != null && !decision.isGranted()) {
|
||||
this.logger.debug(LogMessage.of(() -> "Failed to authorize " + mi + " with authorization manager "
|
||||
+ this.authorizationManager + " and decision " + decision));
|
||||
@@ -152,4 +167,9 @@ public final class AuthorizationManagerAfterMethodInterceptor
|
||||
this.logger.debug(LogMessage.of(() -> "Authorized method invocation " + mi));
|
||||
}
|
||||
|
||||
private static <T> void noPublish(Supplier<Authentication> authentication, T object,
|
||||
AuthorizationDecision decision) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -38,6 +38,7 @@ import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -71,6 +72,8 @@ public final class AuthorizationManagerBeforeMethodInterceptor
|
||||
|
||||
private int order = AuthorizationInterceptorsOrder.FIRST.getOrder();
|
||||
|
||||
private AuthorizationEventPublisher eventPublisher = AuthorizationManagerBeforeMethodInterceptor::noPublish;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
* @param pointcut the {@link Pointcut} to use
|
||||
@@ -168,6 +171,17 @@ public final class AuthorizationManagerBeforeMethodInterceptor
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this {@link AuthorizationEventPublisher} to publish the
|
||||
* {@link AuthorizationManager} result.
|
||||
* @param eventPublisher
|
||||
* @since 5.7
|
||||
*/
|
||||
public void setAuthorizationEventPublisher(AuthorizationEventPublisher eventPublisher) {
|
||||
Assert.notNull(eventPublisher, "eventPublisher cannot be null");
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -189,6 +203,7 @@ public final class AuthorizationManagerBeforeMethodInterceptor
|
||||
private void attemptAuthorization(MethodInvocation mi) {
|
||||
this.logger.debug(LogMessage.of(() -> "Authorizing method invocation " + mi));
|
||||
AuthorizationDecision decision = this.authorizationManager.check(AUTHENTICATION_SUPPLIER, mi);
|
||||
this.eventPublisher.publishAuthorizationEvent(AUTHENTICATION_SUPPLIER, mi, decision);
|
||||
if (decision != null && !decision.isGranted()) {
|
||||
this.logger.debug(LogMessage.of(() -> "Failed to authorize " + mi + " with authorization manager "
|
||||
+ this.authorizationManager + " and decision " + decision));
|
||||
@@ -197,4 +212,9 @@ public final class AuthorizationManagerBeforeMethodInterceptor
|
||||
this.logger.debug(LogMessage.of(() -> "Authorized method invocation " + mi));
|
||||
}
|
||||
|
||||
private static <T> void noPublish(Supplier<Authentication> authentication, T object,
|
||||
AuthorizationDecision decision) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.security.authorization.event.AuthorizationFailureEvent;
|
||||
import org.springframework.security.authorization.event.AuthorizationSuccessEvent;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultAuthorizationEventPublisher}
|
||||
*
|
||||
* @author Parikshit Dutta
|
||||
*/
|
||||
public class DefaultAuthorizationEventPublisherTests {
|
||||
|
||||
ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
DefaultAuthorizationEventPublisher authorizationEventPublisher;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
this.applicationEventPublisher = mock(ApplicationEventPublisher.class);
|
||||
this.authorizationEventPublisher = new DefaultAuthorizationEventPublisher();
|
||||
this.authorizationEventPublisher.setApplicationEventPublisher(this.applicationEventPublisher);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticationSuccessIsPublished() {
|
||||
this.authorizationEventPublisher.publishAuthorizationSuccess(mock(AuthorizationDecision.class));
|
||||
verify(this.applicationEventPublisher).publishEvent(isA(AuthorizationSuccessEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticationFailureIsPublished() {
|
||||
this.authorizationEventPublisher.publishAuthorizationFailure(mock(AuthorizationDecision.class));
|
||||
verify(this.applicationEventPublisher).publishEvent(isA(AuthorizationFailureEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullPublisherNotInvoked() {
|
||||
this.authorizationEventPublisher.setApplicationEventPublisher(null);
|
||||
this.authorizationEventPublisher.publishAuthorizationSuccess(mock(AuthorizationDecision.class));
|
||||
this.authorizationEventPublisher.publishAuthorizationFailure(mock(AuthorizationDecision.class));
|
||||
verify(this.applicationEventPublisher, never()).publishEvent(any());
|
||||
}
|
||||
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.security.authentication.TestAuthentication;
|
||||
import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringAuthorizationEventPublisher}
|
||||
*
|
||||
* @author Parikshit Dutta
|
||||
*/
|
||||
public class SpringAuthorizationEventPublisherTests {
|
||||
|
||||
Supplier<Authentication> authentication = () -> TestAuthentication.authenticatedUser();
|
||||
|
||||
ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
SpringAuthorizationEventPublisher authorizationEventPublisher;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
this.applicationEventPublisher = mock(ApplicationEventPublisher.class);
|
||||
this.authorizationEventPublisher = new SpringAuthorizationEventPublisher(this.applicationEventPublisher);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticationSuccessIsNotPublished() {
|
||||
AuthorizationDecision decision = new AuthorizationDecision(true);
|
||||
this.authorizationEventPublisher.publishAuthorizationEvent(this.authentication, mock(Object.class), decision);
|
||||
verifyNoInteractions(this.applicationEventPublisher);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticationFailureIsPublished() {
|
||||
AuthorizationDecision decision = new AuthorizationDecision(false);
|
||||
this.authorizationEventPublisher.publishAuthorizationEvent(this.authentication, mock(Object.class), decision);
|
||||
verify(this.applicationEventPublisher).publishEvent(isA(AuthorizationDeniedEvent.class));
|
||||
}
|
||||
|
||||
}
|
||||
+38
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,11 +16,20 @@
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
@@ -66,4 +75,32 @@ public class AuthorizationManagerAfterMethodInterceptorTests {
|
||||
any(MethodInvocationResult.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenAuthorizationEventPublisherIsNullThenIllegalArgument() {
|
||||
AuthorizationManagerAfterMethodInterceptor advice = new AuthorizationManagerAfterMethodInterceptor(
|
||||
Pointcut.TRUE, AuthenticatedAuthorizationManager.authenticated());
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> advice.setAuthorizationEventPublisher(null))
|
||||
.withMessage("eventPublisher cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invokeWhenAuthorizationEventPublisherThenUses() throws Throwable {
|
||||
AuthorizationManagerAfterMethodInterceptor advice = new AuthorizationManagerAfterMethodInterceptor(
|
||||
Pointcut.TRUE, AuthenticatedAuthorizationManager.authenticated());
|
||||
AuthorizationEventPublisher eventPublisher = mock(AuthorizationEventPublisher.class);
|
||||
advice.setAuthorizationEventPublisher(eventPublisher);
|
||||
|
||||
SecurityContext securityContext = new SecurityContextImpl();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
|
||||
MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
|
||||
MethodInvocationResult result = new MethodInvocationResult(mockMethodInvocation, new Object());
|
||||
given(mockMethodInvocation.proceed()).willReturn(result.getResult());
|
||||
|
||||
advice.invoke(mockMethodInvocation);
|
||||
verify(eventPublisher).publishAuthorizationEvent(any(Supplier.class), any(MethodInvocationResult.class),
|
||||
any(AuthorizationDecision.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+40
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,13 +16,24 @@
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@@ -59,4 +70,32 @@ public class AuthorizationManagerBeforeMethodInterceptorTests {
|
||||
mockMethodInvocation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenAuthorizationEventPublisherIsNullThenIllegalArgument() {
|
||||
AuthorizationManagerBeforeMethodInterceptor advice = new AuthorizationManagerBeforeMethodInterceptor(
|
||||
Pointcut.TRUE, AuthenticatedAuthorizationManager.authenticated());
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> advice.setAuthorizationEventPublisher(null))
|
||||
.withMessage("eventPublisher cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invokeWhenAuthorizationEventPublisherThenUses() throws Throwable {
|
||||
AuthorizationManagerBeforeMethodInterceptor advice = new AuthorizationManagerBeforeMethodInterceptor(
|
||||
Pointcut.TRUE, AuthenticatedAuthorizationManager.authenticated());
|
||||
AuthorizationEventPublisher eventPublisher = mock(AuthorizationEventPublisher.class);
|
||||
advice.setAuthorizationEventPublisher(eventPublisher);
|
||||
|
||||
SecurityContext securityContext = new SecurityContextImpl();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
|
||||
MethodInvocation mockMethodInvocation = mock(MethodInvocation.class);
|
||||
MethodInvocationResult result = new MethodInvocationResult(mockMethodInvocation, new Object());
|
||||
given(mockMethodInvocation.proceed()).willReturn(result.getResult());
|
||||
|
||||
advice.invoke(mockMethodInvocation);
|
||||
verify(eventPublisher).publishAuthorizationEvent(any(Supplier.class), any(MethodInvocation.class),
|
||||
any(AuthorizationDecision.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user