diff --git a/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java
index 4864ea12ee..d75a2775cd 100644
--- a/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java
+++ b/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -22,6 +22,8 @@ import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.SpringSecurityMessageSource;
@@ -45,7 +47,8 @@ import org.springframework.util.Assert;
* @author EddĂș MelĂ©ndez
* @since 5.2
*/
-public abstract class AbstractUserDetailsReactiveAuthenticationManager implements ReactiveAuthenticationManager {
+public abstract class AbstractUserDetailsReactiveAuthenticationManager
+ implements ReactiveAuthenticationManager, MessageSourceAware {
protected final Log logger = LogFactory.getLog(getClass());
@@ -164,6 +167,15 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement
this.postAuthenticationChecks = postAuthenticationChecks;
}
+ /**
+ * @since 5.5
+ */
+ @Override
+ public void setMessageSource(MessageSource messageSource) {
+ Assert.notNull(messageSource, "messageSource cannot be null");
+ this.messages = new MessageSourceAccessor(messageSource);
+ }
+
/**
* Allows subclasses to retrieve the UserDetails from an
* implementation-specific location.
diff --git a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java
index 06630e17f3..72d05fa063 100644
--- a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java
+++ b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -25,6 +25,7 @@ import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
+import org.springframework.context.MessageSource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
@@ -34,10 +35,12 @@ import org.springframework.security.core.userdetails.UserDetailsChecker;
import org.springframework.security.crypto.password.PasswordEncoder;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willThrow;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -214,4 +217,18 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests {
assertThatExceptionOfType(DisabledException.class).isThrownBy(() -> this.manager.authenticate(token).block());
}
+ @Test
+ public void setMessageSourceWhenNullThenThrowsException() {
+ assertThatIllegalArgumentException().isThrownBy(() -> this.manager.setMessageSource(null));
+ }
+
+ @Test
+ public void setMessageSourceWhenNotNullThenCanGet() {
+ MessageSource source = mock(MessageSource.class);
+ this.manager.setMessageSource(source);
+ String code = "code";
+ this.manager.messages.getMessage(code);
+ verify(source).getMessage(eq(code), any(), any());
+ }
+
}
diff --git a/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java b/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java
index ae7a0367b4..e12bbb53c9 100644
--- a/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java
+++ b/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2016 the original author or authors.
+ * Copyright 2004-2020 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.
@@ -25,6 +25,8 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.log.LogMessage;
import org.springframework.security.access.AccessDeniedException;
@@ -77,7 +79,7 @@ import org.springframework.web.filter.GenericFilterBean;
* @author Ben Alex
* @author colin sampaleanu
*/
-public class ExceptionTranslationFilter extends GenericFilterBean {
+public class ExceptionTranslationFilter extends GenericFilterBean implements MessageSourceAware {
private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();
@@ -89,7 +91,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
private RequestCache requestCache = new HttpSessionRequestCache();
- private final MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
+ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
public ExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint) {
this(authenticationEntryPoint, new HttpSessionRequestCache());
@@ -226,6 +228,15 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
this.throwableAnalyzer = throwableAnalyzer;
}
+ /**
+ * @since 5.5
+ */
+ @Override
+ public void setMessageSource(MessageSource messageSource) {
+ Assert.notNull(messageSource, "messageSource cannot be null");
+ this.messages = new MessageSourceAccessor(messageSource);
+ }
+
/**
* Default implementation of ThrowableAnalyzer which is capable of also
* unwrapping ServletExceptions.
diff --git a/web/src/main/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java b/web/src/main/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java
index 56e5c33b9e..b690af59c0 100644
--- a/web/src/main/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java
+++ b/web/src/main/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -24,6 +24,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.log.LogMessage;
import org.springframework.security.authentication.BadCredentialsException;
@@ -43,7 +44,7 @@ import org.springframework.util.Assert;
*
* @author Luke Taylor
*/
-public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor {
+public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor, MessageSourceAware {
protected final Log logger = LogFactory.getLog(getClass());
@@ -88,7 +89,12 @@ public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor {
this.subjectDnPattern = Pattern.compile(subjectDnRegex, Pattern.CASE_INSENSITIVE);
}
+ /**
+ * @since 5.5
+ */
+ @Override
public void setMessageSource(MessageSource messageSource) {
+ Assert.notNull(messageSource, "messageSource cannot be null");
this.messages = new MessageSourceAccessor(messageSource);
}
diff --git a/web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java b/web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java
index 1d25067d37..b869316c74 100644
--- a/web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java
+++ b/web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -30,6 +30,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.log.LogMessage;
import org.springframework.security.authentication.AccountStatusException;
@@ -59,7 +61,8 @@ import org.springframework.util.StringUtils;
* @author Onur Kagan Ozcan
* @since 2.0
*/
-public abstract class AbstractRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler {
+public abstract class AbstractRememberMeServices
+ implements RememberMeServices, InitializingBean, LogoutHandler, MessageSourceAware {
public static final String SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY = "remember-me";
@@ -71,7 +74,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
protected final Log logger = LogFactory.getLog(getClass());
- protected final MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
+ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private UserDetailsService userDetailsService;
@@ -481,4 +484,13 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
this.authoritiesMapper = authoritiesMapper;
}
+ /**
+ * @since 5.5
+ */
+ @Override
+ public void setMessageSource(MessageSource messageSource) {
+ Assert.notNull(messageSource, "messageSource cannot be null");
+ this.messages = new MessageSourceAccessor(messageSource);
+ }
+
}
diff --git a/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java b/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java
index 77b3560480..3269e20cb1 100644
--- a/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java
+++ b/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2016 the original author or authors.
+ * Copyright 2004-2020 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.
@@ -29,6 +29,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -50,8 +51,10 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
@@ -284,6 +287,22 @@ public class ExceptionTranslationFilterTests {
verifyZeroInteractions(this.mockEntryPoint);
}
+ @Test
+ public void setMessageSourceWhenNullThenThrowsException() {
+ ExceptionTranslationFilter filter = new ExceptionTranslationFilter(this.mockEntryPoint);
+ assertThatIllegalArgumentException().isThrownBy(() -> filter.setMessageSource(null));
+ }
+
+ @Test
+ public void setMessageSourceWhenNotNullThenCanGet() {
+ MessageSource source = mock(MessageSource.class);
+ ExceptionTranslationFilter filter = new ExceptionTranslationFilter(this.mockEntryPoint);
+ filter.setMessageSource(source);
+ String code = "code";
+ filter.messages.getMessage(code);
+ verify(source).getMessage(eq(code), any(), any());
+ }
+
private AuthenticationEntryPoint mockEntryPoint = (request, response, authException) -> response
.sendRedirect(request.getContextPath() + "/login.jsp");
diff --git a/web/src/test/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractorTests.java b/web/src/test/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractorTests.java
index 11c92891a1..5519e6ff1b 100644
--- a/web/src/test/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractorTests.java
+++ b/web/src/test/java/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -19,12 +19,16 @@ package org.springframework.security.web.authentication.preauth.x509;
import org.junit.Before;
import org.junit.Test;
+import org.springframework.context.MessageSource;
import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.core.SpringSecurityMessageSource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
/**
* @author Luke Taylor
@@ -36,7 +40,6 @@ public class SubjectDnX509PrincipalExtractorTests {
@Before
public void setUp() {
this.extractor = new SubjectDnX509PrincipalExtractor();
- this.extractor.setMessageSource(new SpringSecurityMessageSource());
}
@Test
@@ -71,4 +74,18 @@ public class SubjectDnX509PrincipalExtractorTests {
assertThat(principal).isEqualTo("Duke");
}
+ @Test
+ public void setMessageSourceWhenNullThenThrowsException() {
+ assertThatIllegalArgumentException().isThrownBy(() -> this.extractor.setMessageSource(null));
+ }
+
+ @Test
+ public void setMessageSourceWhenNotNullThenCanGet() {
+ MessageSource source = mock(MessageSource.class);
+ this.extractor.setMessageSource(source);
+ String code = "code";
+ this.extractor.messages.getMessage(code);
+ verify(source).getMessage(eq(code), any(), any());
+ }
+
}
diff --git a/web/src/test/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServicesTests.java b/web/src/test/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServicesTests.java
index 038c3cd163..a0be9eec1a 100644
--- a/web/src/test/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServicesTests.java
+++ b/web/src/test/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServicesTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -28,6 +28,7 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.context.MessageSource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.AccountStatusUserDetailsChecker;
@@ -44,6 +45,11 @@ import org.springframework.util.StringUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
/**
* @author Luke Taylor
@@ -411,6 +417,22 @@ public class AbstractRememberMeServicesTests {
assertThat(cookie.getDomain()).isEqualTo("spring.io");
}
+ @Test
+ public void setMessageSourceWhenNullThenThrowsException() {
+ MockRememberMeServices services = new MockRememberMeServices();
+ assertThatIllegalArgumentException().isThrownBy(() -> services.setMessageSource(null));
+ }
+
+ @Test
+ public void setMessageSourceWhenNotNullThenCanGet() {
+ MessageSource source = mock(MessageSource.class);
+ MockRememberMeServices services = new MockRememberMeServices();
+ services.setMessageSource(source);
+ String code = "code";
+ services.messages.getMessage(code);
+ verify(source).getMessage(eq(code), any(), any());
+ }
+
private Cookie[] createLoginCookie(String cookieToken) {
MockRememberMeServices services = new MockRememberMeServices(this.uds);
Cookie cookie = new Cookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,