1
0
mirror of synced 2026-07-08 20:30:04 +00:00

Compare commits

...

21 Commits

Author SHA1 Message Date
github-actions[bot] 612909ac4f Release 5.8.6 2023-08-21 15:21:12 +00:00
Josh Cummings 28f98b3351 Improve Error Message
Closes gh-13667
2023-08-20 22:53:57 -06:00
Josh Cummings ed96e2cddf Ignore Unmappable Servlets
Closes gh-13666
2023-08-20 22:53:55 -06:00
Steve Riesenberg 7200f76ac1 Update org.springframework.data to 2021.2.15
Closes gh-13705
2023-08-18 15:58:36 -05:00
Steve Riesenberg 094b71b329 Update org.aspectj to 1.9.20
Closes gh-13704
2023-08-18 15:58:33 -05:00
Steve Riesenberg 491f0f647c Update io.projectreactor to 2020.0.35
Closes gh-13702
2023-08-18 15:58:27 -05:00
Mario Petrovski 1db8734101 Closes #11450 Add Java beans configuration for Remmember Me Docs 2023-08-09 09:54:53 -03:00
Kawin Naipongprasit 4b44a2d924 Adapeter to Adapter 2023-08-07 15:25:47 -06:00
Daniel Shuy e8b9a35494 Fix Bearer Token RestTemplate Support example 2023-08-07 14:47:37 -06:00
Rob Winch 82e5f62079 Use includeGroupByRegex
This makes the include more robust

Issue gh-13582
2023-08-07 10:26:57 -05:00
Eric Haag 30bc2634d7 Optimize configuration of project repositories
This change applies repository content filtering to configured
repositories, reducing the time spent during dependency resolution.

This fixes an issue where requests for 'org.opensaml',
'net.shibboleth.utilities' and 'net.minidev' dependencies were being
made in the Spring releases repositories, resulting in many failed
requests during dependency resolution and increased resolution times.

Closes gh-13582
2023-08-07 09:51:42 -05:00
Marcus Da Coregio 13ca7ac4d4 Referrer-Policy is added by default in Reactive applications
Closes gh-13561
2023-07-27 11:22:21 -03:00
Josh Cummings c4f061c63d Do Not Re-register Method Security Advisors
Closes gh-13572
2023-07-24 11:24:03 -06:00
Marcus Da Coregio 2c6d053ceb Merge branch '5.7.x' into 5.8.x 2023-07-18 09:51:45 -03:00
Marcus Da Coregio ff4745a461 Merge branch '5.6.x' into 5.7.x 2023-07-18 09:51:19 -03:00
github-actions[bot] 38a7ffcc9b Next development version 2023-07-17 21:52:14 +00:00
github-actions[bot] 6f55fc60bb Next development version 2023-07-17 21:46:35 +00:00
github-actions[bot] d0491c07e9 Next development version 2023-07-17 21:42:28 +00:00
github-actions[bot] 486c5118d2 Release 5.7.10 2023-07-17 21:05:15 +00:00
github-actions[bot] d02ab50577 Release 5.8.5 2023-07-17 21:04:33 +00:00
github-actions[bot] 17d8293be1 Release 5.6.12 2023-07-17 21:00:49 +00:00
15 changed files with 140 additions and 47 deletions
@@ -34,6 +34,14 @@ class RepositoryConventionPlugin implements Plugin<Project> {
if (forceMavenRepositories?.contains('local')) {
mavenLocal()
}
maven {
name = 'shibboleth'
url = 'https://build.shibboleth.net/nexus/content/repositories/releases/'
content {
includeGroupByRegex('org\\.opensaml.*')
includeGroupByRegex('net\\.shibboleth.*')
}
}
mavenCentral()
if (isSnapshot) {
maven {
@@ -67,12 +75,11 @@ class RepositoryConventionPlugin implements Plugin<Project> {
password project.artifactoryPassword
}
}
content {
excludeGroup('net.minidev')
}
url = 'https://repo.spring.io/release/'
}
maven {
name = 'shibboleth'
url = 'https://build.shibboleth.net/nexus/content/repositories/releases/'
}
}
}
@@ -125,27 +125,27 @@ public class RepositoryConventionPluginTests {
private void assertSnapshotRepository(RepositoryHandler repositories) {
assertThat(repositories).extracting(ArtifactRepository::getName).hasSize(5);
assertThat(((MavenArtifactRepository) repositories.get(0)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(1)).getUrl().toString())
.isEqualTo("https://repo.spring.io/snapshot/");
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(2)).getUrl().toString())
.isEqualTo("https://repo.spring.io/snapshot/");
assertThat(((MavenArtifactRepository) repositories.get(3)).getUrl().toString())
.isEqualTo("https://repo.spring.io/milestone/");
}
private void assertMilestoneRepository(RepositoryHandler repositories) {
assertThat(repositories).extracting(ArtifactRepository::getName).hasSize(4);
assertThat(((MavenArtifactRepository) repositories.get(0)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(1)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(2)).getUrl().toString())
.isEqualTo("https://repo.spring.io/milestone/");
}
private void assertReleaseRepository(RepositoryHandler repositories) {
assertThat(repositories).extracting(ArtifactRepository::getName).hasSize(3);
assertThat(((MavenArtifactRepository) repositories.get(0)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(1)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(2)).getUrl().toString())
.isEqualTo("https://repo.spring.io/release/");
}
-4
View File
@@ -4,10 +4,6 @@ apply plugin: 'io.spring.convention.spring-module'
apply plugin: 'trang'
apply plugin: 'kotlin'
repositories {
maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" }
}
dependencies {
management platform(project(":spring-security-dependencies"))
// NB: Don't add other compile time dependencies to the config module as this breaks tooling
@@ -36,6 +36,10 @@ class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
}
private void registerAsAdvisor(String prefix, BeanDefinitionRegistry registry) {
String advisorName = prefix + "Advisor";
if (registry.containsBeanDefinition(advisorName)) {
return;
}
String interceptorName = prefix + "MethodInterceptor";
if (!registry.containsBeanDefinition(interceptorName)) {
return;
@@ -18,6 +18,8 @@ package org.springframework.security.config.annotation.web;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -312,18 +314,31 @@ public abstract class AbstractRequestMatcherRegistry<C> {
if (servletContext == null) {
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
}
Map<String, ? extends ServletRegistration> registrations = servletContext.getServletRegistrations();
if (registrations == null) {
Map<String, ? extends ServletRegistration> registrations = mappableServletRegistrations(servletContext);
if (registrations.isEmpty()) {
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
}
if (!hasDispatcherServlet(registrations)) {
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
}
Assert.isTrue(registrations.size() == 1,
"This method cannot decide whether these patterns are Spring MVC patterns or not. If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); otherwise, please use requestMatchers(AntPathRequestMatcher).");
if (registrations.size() > 1) {
String errorMessage = computeErrorMessage(registrations.values());
throw new IllegalArgumentException(errorMessage);
}
return requestMatchers(createMvcMatchers(method, patterns).toArray(new RequestMatcher[0]));
}
private Map<String, ? extends ServletRegistration> mappableServletRegistrations(ServletContext servletContext) {
Map<String, ServletRegistration> mappable = new LinkedHashMap<>();
for (Map.Entry<String, ? extends ServletRegistration> entry : servletContext.getServletRegistrations()
.entrySet()) {
if (!entry.getValue().getMappings().isEmpty()) {
mappable.put(entry.getKey(), entry.getValue());
}
}
return mappable;
}
private boolean hasDispatcherServlet(Map<String, ? extends ServletRegistration> registrations) {
if (registrations == null) {
return false;
@@ -344,6 +359,19 @@ public abstract class AbstractRequestMatcherRegistry<C> {
return false;
}
private String computeErrorMessage(Collection<? extends ServletRegistration> registrations) {
String template = "This method cannot decide whether these patterns are Spring MVC patterns or not. "
+ "If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); "
+ "otherwise, please use requestMatchers(AntPathRequestMatcher).\n\n"
+ "This is because there is more than one mappable servlet in your servlet context: %s.\n\n"
+ "For each MvcRequestMatcher, call MvcRequestMatcher#setServletPath to indicate the servlet path.";
Map<String, Collection<String>> mappings = new LinkedHashMap<>();
for (ServletRegistration registration : registrations) {
mappings.put(registration.getClassName(), registration.getMappings());
}
return String.format(template, mappings);
}
/**
* <p>
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
@@ -16,8 +16,10 @@
package org.springframework.security.config;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@@ -35,7 +37,7 @@ public class MockServletContext extends org.springframework.mock.web.MockServlet
public static MockServletContext mvc() {
MockServletContext servletContext = new MockServletContext();
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class);
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");
return servletContext;
}
@@ -59,6 +61,8 @@ public class MockServletContext extends org.springframework.mock.web.MockServlet
private final Class<?> clazz;
private final Set<String> mappings = new LinkedHashSet<>();
MockServletRegistration(String name, Class<?> clazz) {
this.name = name;
this.clazz = clazz;
@@ -91,12 +95,13 @@ public class MockServletContext extends org.springframework.mock.web.MockServlet
@Override
public Set<String> addMapping(String... urlPatterns) {
return null;
this.mappings.addAll(Arrays.asList(urlPatterns));
return this.mappings;
}
@Override
public Collection<String> getMappings() {
return null;
return this.mappings;
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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.
@@ -20,6 +20,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.aopalliance.intercept.MethodInterceptor;
@@ -64,6 +65,8 @@ import org.springframework.security.test.context.support.WithSecurityContextTest
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -418,6 +421,17 @@ public class PrePostMethodSecurityConfigurationTests {
assertThat(this.spring.getContext().containsBean("annotationSecurityAspect$0")).isFalse();
}
// gh-13572
@Test
public void configureWhenBeanOverridingDisallowedThenWorks() {
this.spring.register(MethodSecurityServiceConfig.class, BusinessServiceConfig.class)
.postProcessor(disallowBeanOverriding()).autowire();
}
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
}
@EnableMethodSecurity
static class MethodSecurityServiceConfig {
@@ -63,12 +63,13 @@ public class AbstractRequestMatcherRegistryTests {
private WebApplicationContext context;
@BeforeEach
public void setUp() {
public void setUp() throws Exception {
this.matcherRegistry = new TestRequestMatcherRegistry();
this.context = mock(WebApplicationContext.class);
given(this.context.getBean(ObjectPostProcessor.class)).willReturn(NO_OP_OBJECT_POST_PROCESSOR);
given(this.context.getServletContext()).willReturn(MockServletContext.mvc());
this.matcherRegistry.setApplicationContext(this.context);
mockMvcPresentClasspath(true);
}
@Test
@@ -211,12 +212,24 @@ public class AbstractRequestMatcherRegistryTests {
public void requestMatchersWhenAmbiguousServletsThenException() {
MockServletContext servletContext = new MockServletContext();
given(this.context.getServletContext()).willReturn(servletContext);
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class);
servletContext.addServlet("servletTwo", Servlet.class);
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");
servletContext.addServlet("servletTwo", Servlet.class).addMapping("/servlet/**");
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> this.matcherRegistry.requestMatchers("/**"));
}
@Test
public void requestMatchersWhenUnmappableServletsThenSkips() {
mockMvcIntrospector(true);
MockServletContext servletContext = new MockServletContext();
given(this.context.getServletContext()).willReturn(servletContext);
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");
servletContext.addServlet("servletTwo", Servlet.class);
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/**");
assertThat(requestMatchers).hasSize(1);
assertThat(requestMatchers.get(0)).isInstanceOf(MvcRequestMatcher.class);
}
private void mockMvcIntrospector(boolean isPresent) {
ApplicationContext context = this.matcherRegistry.getApplicationContext();
given(context.containsBean("mvcHandlerMappingIntrospector")).willReturn(isPresent);
+2 -2
View File
@@ -8,11 +8,11 @@ javaPlatform {
dependencies {
api platform("org.springframework:spring-framework-bom:$springFrameworkVersion")
api platform("io.projectreactor:reactor-bom:2020.0.34")
api platform("io.projectreactor:reactor-bom:2020.0.35")
api platform("io.rsocket:rsocket-bom:1.1.4")
api platform("org.junit:junit-bom:5.9.3")
api platform("org.mockito:mockito-bom:4.8.1")
api platform("org.springframework.data:spring-data-bom:2021.2.14")
api platform("org.springframework.data:spring-data-bom:2021.2.15")
api platform("org.jetbrains.kotlin:kotlin-bom:$kotlinVersion")
api platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4")
api platform("com.fasterxml.jackson:jackson-bom:2.13.5")
@@ -692,7 +692,7 @@ open class SecurityConfiguration {
=== Publish an `AuthenticationManager` Bean
As part of `WebSecurityConfigurerAdapeter` removal, `configure(AuthenticationManagerBuilder)` is also removed.
As part of `WebSecurityConfigurerAdapter` removal, `configure(AuthenticationManagerBuilder)` is also removed.
Preparing for its removal will differ based on your reason for using it.
==== LDAP Authentication
@@ -410,8 +410,8 @@ fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
[[webflux-headers-referrer]]
== Referrer Policy
Spring Security does not add xref:features/exploits/headers.adoc#headers-referrer[Referrer Policy] headers by default.
You can enable the Referrer Policy header using configuration as shown below:
Spring Security adds the xref:features/exploits/headers.adoc#headers-referrer[Referrer Policy] header by default with the directive `no-referrer`.
You can change the Referrer Policy header using configuration as shown below:
.Referrer Policy Configuration
[tabs]
@@ -159,7 +159,39 @@ XML::
The following beans are required in an application context to enable remember-me services:
[source,xml]
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Bean
RememberMeAuthenticationFilter rememberMeFilter() {
RememberMeAuthenticationFilter rememberMeFilter = new RememberMeAuthenticationFilter();
rememberMeFilter.setRememberMeServices(rememberMeServices());
rememberMeFilter.setAuthenticationManager(theAuthenticationManager);
return rememberMeFilter;
}
@Bean
TokenBasedRememberMeServices rememberMeServices() {
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices();
rememberMeServices.setUserDetailsService(myUserDetailsService);
rememberMeServices.setKey("springRocks");
return rememberMeServices;
}
@Bean
RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
RememberMeAuthenticationProvider rememberMeAuthenticationProvider = new RememberMeAuthenticationProvider();
rememberMeAuthenticationProvider.setKey("springRocks");
return rememberMeAuthenticationProvider;
}
----
XML::
+
[source,xml,role="secondary"]
----
<bean id="rememberMeFilter" class=
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
@@ -178,6 +210,7 @@ The following beans are required in an application context to enable remember-me
<property name="key" value="springRocks"/>
</bean>
----
======
Don't forget to add your `RememberMeServices` implementation to your `UsernamePasswordAuthenticationFilter.setRememberMeServices()` property, include the `RememberMeAuthenticationProvider` in your `AuthenticationManager.setProviders()` list, and add `RememberMeAuthenticationFilter` into your `FilterChainProxy` (typically immediately after your `UsernamePasswordAuthenticationFilter`).
@@ -241,16 +241,15 @@ fun rest(): RestTemplate {
val rest = RestTemplate()
rest.interceptors.add(ClientHttpRequestInterceptor { request, body, execution ->
val authentication: Authentication? = SecurityContextHolder.getContext().authentication
if (authentication != null) {
execution.execute(request, body)
if (authentication == null) {
return execution.execute(request, body)
}
if (authentication!!.credentials !is AbstractOAuth2Token) {
execution.execute(request, body)
if (authentication.credentials !is AbstractOAuth2Token) {
return execution.execute(request, body)
}
val token: AbstractOAuth2Token = authentication.credentials as AbstractOAuth2Token
request.headers.setBearerAuth(token.tokenValue)
request.headers.setBearerAuth(authentication.credentials.tokenValue)
execution.execute(request, body)
})
return rest
+1 -7
View File
@@ -1,6 +1,7 @@
plugins {
id 'org.antora' version '1.0.0'
id 'io.spring.antora.generate-antora-yml' version '0.0.1'
id 'io.spring.convention.repository'
}
apply plugin: 'io.spring.convention.docs'
@@ -59,10 +60,3 @@ def resolvedVersions(Configuration configuration) {
.resolvedArtifacts
.collectEntries { [(it.name + '-version'): it.moduleVersion.id.version] }
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/release' }
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
+2 -2
View File
@@ -1,9 +1,9 @@
aspectjVersion=1.9.19
aspectjVersion=1.9.20
springJavaformatVersion=0.0.39
springBootVersion=2.7.12
springFrameworkVersion=5.3.29
openSamlVersion=3.4.6
version=5.8.5-SNAPSHOT
version=5.8.6
kotlinVersion=1.7.22
samplesBranch=5.8.x
org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError