فهرست منبع

Localize AccessDeniedException message

Closes gh-13419
maimate-dev 2 سال پیش
والد
کامیت
7b2cb59dab

+ 19 - 2
core/src/main/java/org/springframework/security/authorization/ObservationAuthorizationManager.java

@@ -22,8 +22,12 @@ import io.micrometer.observation.Observation;
 import io.micrometer.observation.ObservationConvention;
 import io.micrometer.observation.ObservationRegistry;
 
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
+import org.springframework.context.support.MessageSourceAccessor;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.SpringSecurityMessageSource;
 import org.springframework.util.Assert;
 
 /**
@@ -32,7 +36,7 @@ import org.springframework.util.Assert;
  * @author Josh Cummings
  * @since 6.0
  */
-public final class ObservationAuthorizationManager<T> implements AuthorizationManager<T> {
+public final class ObservationAuthorizationManager<T> implements AuthorizationManager<T>, MessageSourceAware {
 
 	private final ObservationRegistry registry;
 
@@ -40,6 +44,8 @@ public final class ObservationAuthorizationManager<T> implements AuthorizationMa
 
 	private ObservationConvention<AuthorizationObservationContext<?>> convention = new AuthorizationObservationConvention();
 
+	private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
+
 	public ObservationAuthorizationManager(ObservationRegistry registry, AuthorizationManager<T> delegate) {
 		this.registry = registry;
 		this.delegate = delegate;
@@ -57,7 +63,8 @@ public final class ObservationAuthorizationManager<T> implements AuthorizationMa
 			AuthorizationDecision decision = this.delegate.check(wrapped, object);
 			context.setDecision(decision);
 			if (decision != null && !decision.isGranted()) {
-				observation.error(new AccessDeniedException("Access Denied"));
+				observation.error(new AccessDeniedException(
+						this.messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access Denied")));
 			}
 			return decision;
 		}
@@ -81,4 +88,14 @@ public final class ObservationAuthorizationManager<T> implements AuthorizationMa
 		this.convention = convention;
 	}
 
+	/**
+	 * Set the MessageSource that this object runs in.
+	 * @param messageSource The message source to be used by this object
+	 * @since 6.2
+	 */
+	@Override
+	public void setMessageSource(final MessageSource messageSource) {
+		this.messages = new MessageSourceAccessor(messageSource);
+	}
+
 }

+ 9 - 0
core/src/test/java/org/springframework/security/authorization/ObservationAuthorizationManagerTests.java

@@ -16,6 +16,7 @@
 
 package org.springframework.security.authorization;
 
+import java.util.Optional;
 import java.util.function.Supplier;
 
 import io.micrometer.observation.Observation;
@@ -25,6 +26,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 
+import org.springframework.context.MessageSource;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.core.Authentication;
@@ -32,6 +34,7 @@ import org.springframework.security.core.Authentication;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -85,14 +88,20 @@ public class ObservationAuthorizationManagerTests {
 
 	@Test
 	void verifyWhenErrorsThenObserves() {
+		MessageSource source = mock(MessageSource.class);
+		this.tested.setMessageSource(source);
 		given(this.handler.supportsContext(any())).willReturn(true);
 		given(this.authorizationManager.check(any(), any())).willReturn(this.deny);
+		given(source.getMessage(eq("AbstractAccessDecisionManager.accessDenied"), any(), any(), any()))
+				.willReturn("accessDenied");
 		assertThatExceptionOfType(AccessDeniedException.class)
 				.isThrownBy(() -> this.tested.verify(this.token, this.object));
 		ArgumentCaptor<Observation.Context> captor = ArgumentCaptor.forClass(Observation.Context.class);
 		verify(this.handler).onStart(captor.capture());
 		assertThat(captor.getValue().getName()).isEqualTo(AuthorizationObservationConvention.OBSERVATION_NAME);
 		assertThat(captor.getValue().getError()).isInstanceOf(AccessDeniedException.class);
+		assertThat(Optional.ofNullable(captor.getValue().getError()).map(Throwable::getMessage).orElse(""))
+				.isEqualTo("accessDenied");
 		assertThat(captor.getValue()).isInstanceOf(AuthorizationObservationContext.class);
 		AuthorizationObservationContext<?> context = (AuthorizationObservationContext<?>) captor.getValue();
 		assertThat(context.getAuthentication()).isNull();