Compare commits

..

No commits in common. "main" and "7.0.0-M2" have entirely different histories.

585 changed files with 1723 additions and 9204 deletions

View File

@ -17,6 +17,8 @@ package io.spring.gradle;
import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.File;
import java.io.IOException;

View File

@ -23,6 +23,8 @@ import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import static org.assertj.core.api.Assertions.assertThat;
/**

View File

@ -5,6 +5,7 @@ import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

View File

@ -1,7 +1,3 @@
plugins {
id 'security-nullability'
}
apply plugin: 'io.spring.convention.spring-module'
dependencies {

View File

@ -16,8 +16,6 @@
package org.springframework.security.cas;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@ -36,7 +34,7 @@ public class ServiceProperties implements InitializingBean {
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
private @Nullable String service;
private String service;
private boolean authenticateAllArtifacts;
@ -64,7 +62,7 @@ public class ServiceProperties implements InitializingBean {
* </pre>
* @return the URL of the service the user is authenticating to
*/
public final @Nullable String getService() {
public final String getService() {
return this.service;
}

View File

@ -21,8 +21,6 @@ import org.apache.commons.logging.LogFactory;
import org.apereo.cas.client.validation.Assertion;
import org.apereo.cas.client.validation.TicketValidationException;
import org.apereo.cas.client.validation.TicketValidator;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
@ -64,7 +62,6 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
@SuppressWarnings("NullAway.Init")
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
@ -73,13 +70,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
@SuppressWarnings("NullAway.Init")
private String key;
@SuppressWarnings("NullAway.Init")
private TicketValidator ticketValidator;
private @Nullable ServiceProperties serviceProperties;
private ServiceProperties serviceProperties;
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
@ -94,7 +89,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
}
@Override
public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}
@ -134,14 +129,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
try {
Object credentials = authentication.getCredentials();
if (credentials == null) {
throw new BadCredentialsException("Authentication.getCredentials() cannot be null");
}
Assertion assertion = this.ticketValidator.validate(credentials.toString(), getServiceUrl(authentication));
Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(),
getServiceUrl(authentication));
UserDetails userDetails = loadUserByAssertion(assertion);
this.userDetailsChecker.check(userDetails);
return new CasAuthenticationToken(this.key, userDetails, credentials,
return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
}
catch (TicketValidationException ex) {
@ -157,8 +149,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
* @param authentication
* @return
*/
@NullUnmarked
private @Nullable String getServiceUrl(Authentication authentication) {
private String getServiceUrl(Authentication authentication) {
String serviceUrl;
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
return ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
@ -224,7 +215,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
return this.statelessTicketCache;
}
protected @Nullable TicketValidator getTicketValidator() {
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}

View File

@ -19,8 +19,6 @@ package org.springframework.security.cas.authentication;
import java.io.Serial;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;
@ -43,7 +41,7 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
private final String identifier;
private @Nullable Object credentials;
private Object credentials;
/**
* This constructor can be safely used by any code that wishes to create a
@ -88,7 +86,7 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
}
@Override
public @Nullable Object getCredentials() {
public Object getCredentials() {
return this.credentials;
}

View File

@ -16,8 +16,6 @@
package org.springframework.security.cas.authentication;
import org.jspecify.annotations.Nullable;
/**
* Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful
* in instances where storing of tickets for stateless session management is not required.
@ -35,7 +33,7 @@ public final class NullStatelessTicketCache implements StatelessTicketCache {
* @return null since we are not storing any tickets.
*/
@Override
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
return null;
}

View File

@ -18,7 +18,6 @@ package org.springframework.security.cas.authentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.cache.Cache;
import org.springframework.core.log.LogMessage;
@ -43,7 +42,7 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache {
}
@Override
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
final Cache.ValueWrapper element = (serviceTicket != null) ? this.cache.get(serviceTicket) : null;
logger.debug(LogMessage.of(() -> "Cache hit: " + (element != null) + "; service ticket: " + serviceTicket));
return (element != null) ? (CasAuthenticationToken) element.get() : null;

View File

@ -16,8 +16,6 @@
package org.springframework.security.cas.authentication;
import org.jspecify.annotations.Nullable;
/**
* Caches CAS service tickets and CAS proxy tickets for stateless connections.
*
@ -71,7 +69,7 @@ public interface StatelessTicketCache {
* </p>
* @return the fully populated authentication token
*/
@Nullable CasAuthenticationToken getByTicketId(String serviceTicket);
CasAuthenticationToken getByTicketId(String serviceTicket);
/**
* Adds the specified <code>CasAuthenticationToken</code> to the cache.

View File

@ -18,7 +18,4 @@
* An {@code AuthenticationProvider} that can process CAS service tickets and proxy
* tickets.
*/
@NullMarked
package org.springframework.security.cas.authentication;
import org.jspecify.annotations.NullMarked;

View File

@ -1,23 +0,0 @@
/*
* Copyright 2004-present 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.
*/
/**
* Jackson support for CAS.
*/
@NullMarked
package org.springframework.security.cas.jackson2;
import org.jspecify.annotations.NullMarked;

View File

@ -18,7 +18,4 @@
* Spring Security support for Apereo's Central Authentication Service
* (<a href="https://github.com/apereo/cas">CAS</a>).
*/
@NullMarked
package org.springframework.security.cas;
import org.jspecify.annotations.NullMarked;

View File

@ -1,23 +0,0 @@
/*
* Copyright 2004-present 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.
*/
/**
* {@link org.springframework.security.core.userdetails.UserDetails} abstractions for CAS.
*/
@NullMarked
package org.springframework.security.cas.userdetails;
import org.jspecify.annotations.NullMarked;

View File

@ -22,7 +22,6 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apereo.cas.client.util.CommonUtils;
import org.apereo.cas.client.util.WebUtils;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.cas.ServiceProperties;
@ -48,10 +47,9 @@ import org.springframework.util.Assert;
*/
public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
@SuppressWarnings("NullAway.Init")
private ServiceProperties serviceProperties;
private @Nullable String loginUrl;
private String loginUrl;
/**
* Determines whether the Service URL should include the session id for the specific
@ -119,7 +117,7 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
* <code>https://www.mycompany.com/cas/login</code>.
* @return the enterprise-wide CAS login URL
*/
public final @Nullable String getLoginUrl() {
public final String getLoginUrl() {
return this.loginUrl;
}

View File

@ -26,7 +26,6 @@ import jakarta.servlet.http.HttpSession;
import org.apereo.cas.client.proxy.ProxyGrantingTicketStorage;
import org.apereo.cas.client.util.WebUtils;
import org.apereo.cas.client.validation.TicketValidator;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage;
import org.springframework.security.authentication.AuthenticationDetailsSource;
@ -191,12 +190,12 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
/**
* The last portion of the receptor url, i.e. /proxy/receptor
*/
private @Nullable RequestMatcher proxyReceptorMatcher;
private RequestMatcher proxyReceptorMatcher;
/**
* The backing storage to store ProxyGrantingTicket requests.
*/
private @Nullable ProxyGrantingTicketStorage proxyGrantingTicketStorage;
private ProxyGrantingTicketStorage proxyGrantingTicketStorage;
private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
@ -245,7 +244,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
}
@Override
public @Nullable Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException {
// if the request is a proxy request process it and return null to indicate the
// request has been processed
@ -423,7 +422,6 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
* @param request
* @return
*/
@SuppressWarnings("NullAway") // Dataflow analysis limitation
private boolean proxyReceptorRequest(HttpServletRequest request) {
final boolean result = proxyReceptorConfigured() && this.proxyReceptorMatcher.matches(request);
this.logger.debug(LogMessage.format("proxyReceptorRequest = %s", result));

View File

@ -21,7 +21,6 @@ import java.net.URL;
import java.util.regex.Pattern;
import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.security.cas.authentication.ServiceAuthenticationDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
@ -50,8 +49,8 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
* string from containing the artifact name and value. This can be created using
* {@link #createArtifactPattern(String)}.
*/
DefaultServiceAuthenticationDetails(@Nullable String casService, HttpServletRequest request,
Pattern artifactPattern) throws MalformedURLException {
DefaultServiceAuthenticationDetails(String casService, HttpServletRequest request, Pattern artifactPattern)
throws MalformedURLException {
super(request);
URL casServiceUrl = new URL(casService);
int port = getServicePort(casServiceUrl);
@ -105,7 +104,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
* @return the query String minus the artifactParameterName and the corresponding
* value.
*/
private @Nullable String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
private String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
final String query = request.getQueryString();
if (query == null) {
return null;

View File

@ -18,7 +18,4 @@
* Authentication processing mechanisms which respond to the submission of authentication
* credentials using CAS.
*/
@NullMarked
package org.springframework.security.cas.web.authentication;
import org.jspecify.annotations.NullMarked;

View File

@ -17,7 +17,4 @@
/**
* Authenticates standard web browser users via CAS.
*/
@NullMarked
package org.springframework.security.cas.web;
import org.jspecify.annotations.NullMarked;

View File

@ -25,6 +25,7 @@ dependencies {
optional project(':spring-security-ldap')
optional project(':spring-security-messaging')
optional project(path: ':spring-security-saml2-service-provider')
opensaml5 project(path: ':spring-security-saml2-service-provider', configuration: 'opensamlFiveMain')
optional project(':spring-security-oauth2-client')
optional project(':spring-security-oauth2-jose')
optional project(':spring-security-oauth2-resource-server')
@ -169,3 +170,15 @@ test {
}
}
}
tasks.register("opensaml5Test", Test) {
filter {
includeTestsMatching "org.springframework.security.config.annotation.web.configurers.saml2.*"
}
useJUnitPlatform()
classpath = sourceSets.main.output + sourceSets.test.output + configurations.opensaml5
}
tasks.named("check") {
dependsOn opensaml5Test
}

View File

@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.authentication.ldap;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Collections;
import java.util.List;
import javax.naming.directory.SearchControls;
@ -38,6 +39,7 @@ import org.springframework.security.config.annotation.configuration.ObjectPostPr
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
@ -118,7 +120,8 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
this.spring.register(BindAuthenticationConfig.class).autowire();
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
.andExpect(authenticated().withUsername("bob").withRoles("DEVELOPERS"));
.andExpect(authenticated().withUsername("bob")
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
}
// SEC-2472
@ -127,7 +130,8 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
this.spring.register(PasswordEncoderConfig.class).autowire();
this.mockMvc.perform(formLogin().user("bcrypt").password("password"))
.andExpect(authenticated().withUsername("bcrypt").withRoles("DEVELOPERS"));
.andExpect(authenticated().withUsername("bcrypt")
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
}
private LdapAuthenticationProvider ldapProvider() {

View File

@ -16,6 +16,8 @@
package org.springframework.security.config.annotation.authentication.ldap;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -26,6 +28,8 @@ import org.springframework.security.config.annotation.authentication.ldap.LdapAu
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
import org.springframework.test.web.servlet.MockMvc;
@ -60,7 +64,7 @@ public class LdapAuthenticationProviderConfigurerTests {
.password("bobspassword");
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
.withUsername("bob")
.withRoles("DEVELOPERS");
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")));
// @formatter:on
this.mockMvc.perform(request).andExpect(expectedUser);
}
@ -75,7 +79,7 @@ public class LdapAuthenticationProviderConfigurerTests {
.password("bobspassword");
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
.withUsername("bob")
.withRoles("ROL_", new String[] { "DEVELOPERS" });
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS")));
// @formatter:on
this.mockMvc.perform(request).andExpect(expectedUser);
}
@ -104,7 +108,8 @@ public class LdapAuthenticationProviderConfigurerTests {
.password("otherbenspassword");
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
.withUsername("otherben")
.withRoles("SUBMANAGERS", "MANAGERS", "DEVELOPERS");
.withAuthorities(
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS"));
// @formatter:on
this.mockMvc.perform(request).andExpect(expectedUser);
}

View File

@ -16,6 +16,7 @@
package org.springframework.security.config.annotation.authentication.ldap;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -33,6 +34,7 @@ import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
@ -77,7 +79,7 @@ public class NamespaceLdapAuthenticationProviderTests {
.user("bob")
.password("bobspassword");
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
.withRoles("PREFIX_", new String[] { "DEVELOPERS" });
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS")));
// @formatter:on
this.mockMvc.perform(request).andExpect(user);
}
@ -101,7 +103,7 @@ public class NamespaceLdapAuthenticationProviderTests {
.user("bob")
.password("bobspassword");
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
.withRoles("EXTRA");
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")));
// @formatter:on
this.mockMvc.perform(request).andExpect(user);
}

View File

@ -1,147 +0,0 @@
/*
* Copyright 2004-present 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.config.annotation.rsocket;
import java.util.ArrayList;
import java.util.List;
import io.rsocket.core.RSocketServer;
import io.rsocket.exceptions.RejectedSetupException;
import io.rsocket.frame.decoder.PayloadDecoder;
import io.rsocket.transport.netty.server.CloseableChannel;
import io.rsocket.transport.netty.server.TcpServerTransport;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
import org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor;
import org.springframework.security.rsocket.util.matcher.PayloadExchangeAuthorizationContext;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Andrey Litvitski
*/
@ContextConfiguration
@ExtendWith(SpringExtension.class)
public class AnonymousAuthenticationITests {
@Autowired
RSocketMessageHandler handler;
@Autowired
SecuritySocketAcceptorInterceptor interceptor;
@Autowired
ServerController controller;
private CloseableChannel server;
private RSocketRequester requester;
@BeforeEach
public void setup() {
// @formatter:off
this.server = RSocketServer.create()
.payloadDecoder(PayloadDecoder.ZERO_COPY)
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
)
.acceptor(this.handler.responder())
.bind(TcpServerTransport.create("localhost", 0))
.block();
// @formatter:on
}
@AfterEach
public void dispose() {
this.requester.rsocket().dispose();
this.server.dispose();
this.controller.payloads.clear();
}
@Test
public void requestWhenAnonymousDisabledThenRespondsWithForbidden() {
this.requester = RSocketRequester.builder()
.rsocketStrategies(this.handler.getRSocketStrategies())
.connectTcp("localhost", this.server.address().getPort())
.block();
String data = "andrew";
assertThatExceptionOfType(RejectedSetupException.class).isThrownBy(
() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block());
assertThat(this.controller.payloads).isEmpty();
}
@Configuration
@EnableRSocketSecurity
static class Config {
@Bean
ServerController controller() {
return new ServerController();
}
@Bean
RSocketMessageHandler messageHandler() {
return new RSocketMessageHandler();
}
@Bean
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
ReactiveAuthorizationManager<PayloadExchangeAuthorizationContext> anonymous = (authentication,
exchange) -> authentication.map(trustResolver::isAnonymous).map(AuthorizationDecision::new);
rsocket.authorizePayload((authorize) -> authorize.anyExchange().access(anonymous));
rsocket.anonymous((anonymousAuthentication) -> anonymousAuthentication.disable());
return rsocket.build();
}
}
@Controller
static class ServerController {
private List<String> payloads = new ArrayList<>();
@MessageMapping("**")
String retrieveMono(String payload) {
add(payload);
return "Hi " + payload;
}
private void add(String p) {
this.payloads.add(p);
}
}
}

View File

@ -169,7 +169,7 @@ public class LdapProviderBeanDefinitionParserTests {
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server />" + "<authentication-manager>"
+ " <ldap-authentication-provider user-dn-pattern='uid={0},ou=${udp}' group-search-filter='${gsf}={0}' />"
+ "</authentication-manager>"
+ "<b:bean id='org.springframework.context.support.PropertySourcesPlaceholderConfigurer' class='org.springframework.context.support.PropertySourcesPlaceholderConfigurer' />");
+ "<b:bean id='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' />");
ProviderManager providerManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
assertThat(providerManager.getProviders()).hasSize(1);

View File

@ -1,52 +0,0 @@
/*
* Copyright 2004-present 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.config;
/**
* A {@link Customizer} that allows invocation of code that throws a checked exception.
*
* @param <T> The type of input.
*/
@FunctionalInterface
public interface ThrowingCustomizer<T> extends Customizer<T> {
/**
* Default {@link Customizer#customize(Object)} that wraps any thrown checked
* exceptions (by default in a {@link RuntimeException}).
* @param t the object to customize
*/
default void customize(T t) {
try {
customizeWithException(t);
}
catch (RuntimeException ex) {
throw ex;
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* Performs the customization on the given object, possibly throwing a checked
* exception.
* @param t the object to customize
* @throws Exception on error
*/
void customizeWithException(T t) throws Exception;
}

View File

@ -102,7 +102,9 @@ class AuthorizationProxyWebConfiguration implements WebMvcConfigurer {
Throwable accessDeniedException = this.throwableAnalyzer
.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
if (accessDeniedException != null) {
throw (AccessDeniedException) accessDeniedException;
return new ModelAndView((model, req, res) -> {
throw ex;
});
}
return null;
}

View File

@ -109,7 +109,6 @@ import org.springframework.security.rsocket.util.matcher.RoutePayloadExchangeMat
* @author Manuel Tejeda
* @author Ebert Toribio
* @author Ngoc Nhan
* @author Andrey Litvitski
* @since 5.2
*/
public class RSocketSecurity {
@ -120,8 +119,6 @@ public class RSocketSecurity {
private SimpleAuthenticationSpec simpleAuthSpec;
private AnonymousAuthenticationSpec anonymousAuthSpec = new AnonymousAuthenticationSpec(this);
private JwtSpec jwtSpec;
private AuthorizePayloadsSpec authorizePayload;
@ -167,20 +164,6 @@ public class RSocketSecurity {
return this;
}
/**
* Adds anonymous authentication
* @param anonymous a customizer
* @return this instance
* @since 7.0
*/
public RSocketSecurity anonymous(Customizer<AnonymousAuthenticationSpec> anonymous) {
if (this.anonymousAuthSpec == null) {
this.anonymousAuthSpec = new AnonymousAuthenticationSpec(this);
}
anonymous.customize(this.anonymousAuthSpec);
return this;
}
/**
* Adds authentication with BasicAuthenticationPayloadExchangeConverter.
* @param basic
@ -231,9 +214,7 @@ public class RSocketSecurity {
if (this.jwtSpec != null) {
result.addAll(this.jwtSpec.build());
}
if (this.anonymousAuthSpec != null) {
result.add(this.anonymousAuthSpec.build());
}
result.add(anonymous());
if (this.authorizePayload != null) {
result.add(this.authorizePayload.build());
}
@ -241,6 +222,12 @@ public class RSocketSecurity {
return result;
}
private AnonymousPayloadInterceptor anonymous() {
AnonymousPayloadInterceptor result = new AnonymousPayloadInterceptor("anonymousUser");
result.setOrder(PayloadInterceptorOrder.ANONYMOUS.getOrder());
return result;
}
private <T> T getBean(Class<T> beanClass) {
if (this.context == null) {
return null;
@ -296,26 +283,6 @@ public class RSocketSecurity {
}
public final class AnonymousAuthenticationSpec {
private RSocketSecurity parent;
private AnonymousAuthenticationSpec(RSocketSecurity parent) {
this.parent = parent;
}
protected AnonymousPayloadInterceptor build() {
AnonymousPayloadInterceptor result = new AnonymousPayloadInterceptor("anonymousUser");
result.setOrder(PayloadInterceptorOrder.ANONYMOUS.getOrder());
return result;
}
public void disable() {
this.parent.anonymousAuthSpec = null;
}
}
public final class BasicAuthenticationSpec {
private ReactiveAuthenticationManager authenticationManager;

View File

@ -16,24 +16,19 @@
package org.springframework.security.config.annotation.web.configuration;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
@ -51,7 +46,6 @@ import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.function.ThrowingSupplier;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
@ -137,8 +131,6 @@ class HttpSecurityConfiguration {
// @formatter:on
applyCorsIfAvailable(http);
applyDefaultConfigurers(http);
applyHttpSecurityCustomizers(this.context, http);
applyTopLevelCustomizers(this.context, http);
return http;
}
@ -168,73 +160,6 @@ class HttpSecurityConfiguration {
}
}
/**
* Applies all {@code Customizer<HttpSecurity>} Bean instances to the
* {@link HttpSecurity} instance.
* @param applicationContext the {@link ApplicationContext} to lookup Bean instances
* @param http the {@link HttpSecurity} to apply the Beans to.
*/
private void applyHttpSecurityCustomizers(ApplicationContext applicationContext, HttpSecurity http) {
ResolvableType httpSecurityCustomizerType = ResolvableType.forClassWithGenerics(Customizer.class,
HttpSecurity.class);
ObjectProvider<Customizer<HttpSecurity>> customizerProvider = this.context
.getBeanProvider(httpSecurityCustomizerType);
// @formatter:off
customizerProvider.orderedStream().forEach((customizer) ->
customizer.customize(http)
);
// @formatter:on
}
/**
* Applies all {@link Customizer} Beans to {@link HttpSecurity}. For each public,
* non-static method in HttpSecurity that accepts a Customizer
* <ul>
* <li>Use the {@link MethodParameter} (this preserves generics) to resolve all Beans
* for that type</li>
* <li>For each {@link Customizer} Bean invoke the {@link java.lang.reflect.Method}
* with the {@link Customizer} Bean as the argument</li>
* </ul>
* @param context the {@link ApplicationContext}
* @param http the {@link HttpSecurity}
* @throws Exception
*/
private void applyTopLevelCustomizers(ApplicationContext context, HttpSecurity http) {
ReflectionUtils.MethodFilter isCustomizerMethod = (method) -> {
if (Modifier.isStatic(method.getModifiers())) {
return false;
}
if (!Modifier.isPublic(method.getModifiers())) {
return false;
}
if (!method.canAccess(http)) {
return false;
}
if (method.getParameterCount() != 1) {
return false;
}
if (method.getParameterTypes()[0] == Customizer.class) {
return true;
}
return false;
};
ReflectionUtils.MethodCallback invokeWithEachCustomizerBean = (customizerMethod) -> {
MethodParameter customizerParameter = new MethodParameter(customizerMethod, 0);
ResolvableType customizerType = ResolvableType.forMethodParameter(customizerParameter);
ObjectProvider<?> customizerProvider = context.getBeanProvider(customizerType);
// @formatter:off
customizerProvider.orderedStream().forEach((customizer) ->
ReflectionUtils.invokeMethod(customizerMethod, http, customizer)
);
// @formatter:on
};
ReflectionUtils.doWithMethods(HttpSecurity.class, invokeWithEachCustomizerBean, isCustomizerMethod);
}
private Map<Class<?>, Object> createSharedObjects() {
Map<Class<?>, Object> sharedObjects = new HashMap<>();
sharedObjects.put(ApplicationContext.class, this.context);

View File

@ -33,6 +33,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@ -78,7 +79,6 @@ import org.springframework.web.filter.ServletRequestPathFilter;
*
* @author Rob Winch
* @author Keesun Baik
* @author Yanming Zhou
* @since 3.2
* @see EnableWebSecurity
* @see WebSecurity
@ -190,7 +190,7 @@ public class WebSecurityConfiguration implements ImportAware {
}
@Bean
public static RsaKeyConversionServicePostProcessor conversionServicePostProcessor() {
public static BeanFactoryPostProcessor conversionServicePostProcessor() {
return new RsaKeyConversionServicePostProcessor();
}

View File

@ -16,7 +16,6 @@
package org.springframework.security.config.annotation.web.reactive;
import java.lang.reflect.Modifier;
import java.util.Map;
import org.springframework.beans.BeansException;
@ -29,13 +28,10 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.authentication.password.ReactiveCompromisedPasswordChecker;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.ObjectPostProcessor;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
@ -44,7 +40,6 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.reactive.result.method.annotation.AuthenticationPrincipalArgumentResolver;
import org.springframework.security.web.reactive.result.method.annotation.CurrentSecurityContextArgumentResolver;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
@ -159,83 +154,6 @@ class ServerHttpSecurityConfiguration {
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
ServerHttpSecurity httpSecurity(ApplicationContext context) {
ServerHttpSecurity http = httpSecurity();
applyServerHttpSecurityCustomizers(context, http);
applyTopLevelBeanCustomizers(context, http);
return http;
}
/**
* Applies all {@code Custmizer<ServerHttpSecurity>} Beans to
* {@link ServerHttpSecurity}.
* @param context the {@link ApplicationContext}
* @param http the {@link ServerHttpSecurity}
* @throws Exception
*/
private void applyServerHttpSecurityCustomizers(ApplicationContext context, ServerHttpSecurity http) {
ResolvableType httpSecurityCustomizerType = ResolvableType.forClassWithGenerics(Customizer.class,
ServerHttpSecurity.class);
ObjectProvider<Customizer<ServerHttpSecurity>> customizerProvider = context
.getBeanProvider(httpSecurityCustomizerType);
// @formatter:off
customizerProvider.orderedStream().forEach((customizer) ->
customizer.customize(http)
);
// @formatter:on
}
/**
* Applies all {@link Customizer} Beans to top level {@link ServerHttpSecurity}
* method.
*
* For each public, non-static method in ServerHttpSecurity that accepts a Customizer
* <ul>
* <li>Use the {@link MethodParameter} (this preserves generics) to resolve all Beans
* for that type</li>
* <li>For each {@link Customizer} Bean invoke the {@link java.lang.reflect.Method}
* with the {@link Customizer} Bean as the argument</li>
* </ul>
* @param context the {@link ApplicationContext}
* @param http the {@link ServerHttpSecurity}
* @throws Exception
*/
private void applyTopLevelBeanCustomizers(ApplicationContext context, ServerHttpSecurity http) {
ReflectionUtils.MethodFilter isCustomizerMethod = (method) -> {
if (Modifier.isStatic(method.getModifiers())) {
return false;
}
if (!Modifier.isPublic(method.getModifiers())) {
return false;
}
if (!method.canAccess(http)) {
return false;
}
if (method.getParameterCount() != 1) {
return false;
}
if (method.getParameterTypes()[0] == Customizer.class) {
return true;
}
return false;
};
ReflectionUtils.MethodCallback invokeWithEachCustomizerBean = (customizerMethod) -> {
MethodParameter customizerParameter = new MethodParameter(customizerMethod, 0);
ResolvableType customizerType = ResolvableType.forMethodParameter(customizerParameter);
ObjectProvider<?> customizerProvider = context.getBeanProvider(customizerType);
// @formatter:off
customizerProvider.orderedStream().forEach((customizer) ->
ReflectionUtils.invokeMethod(customizerMethod, http, customizer)
);
// @formatter:on
};
ReflectionUtils.doWithMethods(ServerHttpSecurity.class, invokeWithEachCustomizerBean, isCustomizerMethod);
}
ServerHttpSecurity httpSecurity() {
ContextAwareServerHttpSecurity http = new ContextAwareServerHttpSecurity();
// @formatter:off

View File

@ -21,6 +21,7 @@ import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -43,13 +44,12 @@ import static org.springframework.security.config.Customizer.withDefaults;
/**
* @author Rob Winch
* @author Yanming Zhou
* @since 5.0
*/
@Configuration(proxyBeanMethods = false)
class WebFluxSecurityConfiguration {
public static final int WEB_FILTER_CHAIN_FILTER_ORDER = -100;
public static final int WEB_FILTER_CHAIN_FILTER_ORDER = 0 - 100;
private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration.";
@ -100,7 +100,7 @@ class WebFluxSecurityConfiguration {
}
@Bean
static RsaKeyConversionServicePostProcessor conversionServicePostProcessor() {
static BeanFactoryPostProcessor conversionServicePostProcessor() {
return new RsaKeyConversionServicePostProcessor();
}

View File

@ -20,7 +20,6 @@ import java.util.Map;
import java.util.function.Supplier;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AopUtils;
@ -38,8 +37,7 @@ class PointcutDelegatingAuthorizationManager implements AuthorizationManager<Met
}
@Override
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
MethodInvocation object) {
public AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation object) {
for (Map.Entry<Pointcut, AuthorizationManager<MethodInvocation>> entry : this.managers.entrySet()) {
Class<?> targetClass = (object.getThis() != null) ? AopUtils.getTargetClass(object.getThis()) : null;
if (entry.getKey().getClassFilter().matches(targetClass)

View File

@ -1316,10 +1316,6 @@ public class ServerHttpSecurity {
return this.context.getBeanNamesForType(beanClass);
}
ApplicationContext getApplicationContext() {
return this.context;
}
protected void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@ -3033,8 +3029,7 @@ public class ServerHttpSecurity {
/**
* Configures the logout handler. Default is
* {@code SecurityContextServerLogoutHandler}. This clears any previous handlers
* configured.
* {@code SecurityContextServerLogoutHandler}
* @param logoutHandler
* @return the {@link LogoutSpec} to configure
*/
@ -3050,18 +3045,6 @@ public class ServerHttpSecurity {
return this;
}
/**
* Allows managing the list of {@link ServerLogoutHandler} instances.
* @param handlersConsumer {@link Consumer} for managing the list of handlers.
* @return the {@link LogoutSpec} to configure
* @since 7.0
*/
public LogoutSpec logoutHandler(Consumer<List<ServerLogoutHandler>> handlersConsumer) {
Assert.notNull(handlersConsumer, "consumer cannot be null");
handlersConsumer.accept(this.logoutHandlers);
return this;
}
/**
* Configures what URL a POST to will trigger a log out.
* @param logoutUrl the url to trigger a log out (i.e. "/signout" would mean a

View File

@ -25,7 +25,6 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.w3c.dom.Element;
import org.springframework.beans.BeansException;
@ -459,7 +458,7 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
}
@Override
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
public AuthorizationResult authorize(Supplier<Authentication> authentication,
MessageAuthorizationContext<?> object) {
EvaluationContext context = this.expressionHandler.createEvaluationContext(authentication, object);
boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, context);

View File

@ -29,6 +29,7 @@ import org.springframework.security.config.annotation.web.configurers.AuthorizeH
import org.springframework.security.config.core.GrantedAuthorityDefaults
import org.springframework.security.core.Authentication
import org.springframework.security.web.access.IpAddressAuthorizationManager
import org.springframework.security.web.access.intercept.AuthorizationFilter
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
import org.springframework.security.web.util.matcher.AnyRequestMatcher
@ -234,13 +235,13 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
* Specify that URLs are allowed by anyone.
*/
val permitAll: AuthorizationManager<RequestAuthorizationContext> =
AuthorizationManager { _: Supplier<out Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
AuthorizationManager { _: Supplier<Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
/**
* Specify that URLs are not allowed by anyone.
*/
val denyAll: AuthorizationManager<RequestAuthorizationContext> =
AuthorizationManager { _: Supplier<out Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
AuthorizationManager { _: Supplier<Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
/**
* Specify that URLs are allowed by any authenticated user.

View File

@ -18,22 +18,14 @@ package org.springframework.security.config.annotation.web
import jakarta.servlet.Filter
import jakarta.servlet.http.HttpServletRequest
import org.springframework.beans.factory.ObjectProvider
import org.springframework.context.ApplicationContext
import org.springframework.core.MethodParameter
import org.springframework.core.ResolvableType
import org.springframework.core.annotation.AnnotationUtils
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.SecurityConfigurerAdapter
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository
import org.springframework.security.web.DefaultSecurityFilterChain
import org.springframework.security.web.util.matcher.RequestMatcher
import org.springframework.util.ReflectionUtils
import java.lang.reflect.Method
import java.lang.reflect.Modifier
/**
* Configures [HttpSecurity] using a [HttpSecurity Kotlin DSL][HttpSecurityDsl].
@ -85,117 +77,6 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
var authenticationManager: AuthenticationManager? = null
val context: ApplicationContext = http.getSharedObject(ApplicationContext::class.java)
init {
applyFunction1HttpSecurityDslBeans(this.context, this)
applyTopLevelFunction1SecurityDslBeans(this.context, this)
}
/**
* Applies all `Function1<HttpSecurity,Unit>` Beans which
* allows exposing the DSL as Beans to be applied.
*
* ```
* @Bean
* fun httpSecurityDslBean(): HttpSecurityDsl.() -> Unit {
* return {
* headers {
* contentSecurityPolicy {
* policyDirectives = "object-src 'none'"
* }
* }
* redirectToHttps { }
* }
* }
* ```
*/
private fun applyFunction1HttpSecurityDslBeans(context: ApplicationContext, http: HttpSecurityDsl) : Unit {
val httpSecurityDslFnType = ResolvableType.forClassWithGenerics(Function1::class.java,
HttpSecurityDsl::class.java, Unit::class.java)
val httpSecurityDslFnProvider = context
.getBeanProvider<Function1<HttpSecurityDsl,Unit>>(httpSecurityDslFnType)
// @formatter:off
httpSecurityDslFnProvider.orderedStream().forEach { fn -> fn.invoke(http) }
// @formatter:on
}
/**
* Applies all `Function1<T,Unit>` Beans such that `T` is a top level
* DSL on `HttpSecurityDsl`. This allows exposing the top level
* DSLs as Beans to be applied.
*
*
* ```
* @Bean
* fun httpSecurityCustomizer(): ThrowingCustomizer<HttpSecurity> {
* return ThrowingCustomizer { http -> http
* .headers { headers -> headers
* .contentSecurityPolicy { csp -> csp
* .policyDirectives("object-src 'none'")
* }
* }
* .redirectToHttps(Customizer.withDefaults())
* }
* }
* ```
*
* @param context the [ApplicationContext]
* @param http the [HttpSecurity]
* @throws Exception
*/
private fun applyTopLevelFunction1SecurityDslBeans(context: ApplicationContext, http: HttpSecurityDsl) {
val isCustomizerMethod = ReflectionUtils.MethodFilter { method: Method ->
if (Modifier.isStatic(method.modifiers)) {
return@MethodFilter false
}
if (!Modifier.isPublic(method.modifiers)) {
return@MethodFilter false
}
if (!method.canAccess(http)) {
return@MethodFilter false
}
if (method.parameterCount != 1) {
return@MethodFilter false
}
return@MethodFilter extractDslType(method) != null
}
val invokeWithEachDslBean = ReflectionUtils.MethodCallback { dslMethod: Method ->
val dslFunctionType = firstMethodResolvableType(dslMethod)!!
val dslFunctionProvider: ObjectProvider<*> = context.getBeanProvider<Any>(dslFunctionType)
// @formatter:off
dslFunctionProvider.orderedStream().forEach {customizer: Any -> ReflectionUtils.invokeMethod(dslMethod, http, customizer)}
}
ReflectionUtils.doWithMethods(HttpSecurityDsl::class.java, invokeWithEachDslBean, isCustomizerMethod)
}
/**
* From a `Method` with the first argument `Function<T,Unit>` return `T` or `null`
* if the first argument is not a `Function`.
* @return From a `Method` with the first argument `Function<T,Unit>` return `T`.
*/
private fun extractDslType(method: Method): ResolvableType? {
val functionType = firstMethodResolvableType(method)
if (!Function::class.java.isAssignableFrom(functionType.toClass())) {
return null
}
val functionInputType = functionType.getGeneric(0)
val securityMarker = AnnotationUtils.findAnnotation(functionInputType.toClass(), SecurityMarker::class.java)
val isSecurityDsl = securityMarker != null
if (!isSecurityDsl) {
return null
}
return functionInputType
}
private fun firstMethodResolvableType(method: Method): ResolvableType {
val parameter = MethodParameter(
method, 0
)
return ResolvableType.forMethodParameter(parameter)
}
/**
* Applies a [SecurityConfigurerAdapter] to this [HttpSecurity]
*

View File

@ -33,7 +33,6 @@ import org.springframework.security.web.util.matcher.RequestMatcher
* @property channelProcessors the [ChannelProcessor] instances to use in
* [ChannelDecisionManagerImpl]
*/
@Deprecated(message="since 6.5 use redirectToHttps instead")
class RequiresChannelDsl : AbstractRequestMatcherDsl() {
private val channelSecurityRules = mutableListOf<AuthorizationRule>()

View File

@ -16,23 +16,13 @@
package org.springframework.security.config.web.server
import org.springframework.beans.factory.ObjectProvider
import org.springframework.context.ApplicationContext
import org.springframework.core.MethodParameter
import org.springframework.core.ResolvableType
import org.springframework.core.annotation.AnnotationUtils
import org.springframework.security.authentication.ReactiveAuthenticationManager
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository
import org.springframework.security.web.server.SecurityWebFilterChain
import org.springframework.security.web.server.context.ServerSecurityContextRepository
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher
import org.springframework.util.ReflectionUtils
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebFilter
import java.lang.reflect.Method
import java.lang.reflect.Modifier
/**
* Configures [ServerHttpSecurity] using a [ServerHttpSecurity Kotlin DSL][ServerHttpSecurityDsl].
@ -78,115 +68,6 @@ class ServerHttpSecurityDsl(private val http: ServerHttpSecurity, private val in
var authenticationManager: ReactiveAuthenticationManager? = null
var securityContextRepository: ServerSecurityContextRepository? = null
init {
applyFunction1HttpSecurityDslBeans(this.http.applicationContext, this)
applyTopLevelFunction1SecurityDslBeans(this.http.applicationContext, this)
}
/**
* Applies all `Function1<ServerHttpSecurityDsl,Unit>` Beans which
* allows exposing the DSL as Beans to be applied.
*
* ```
* @Bean
* @Order(Ordered.LOWEST_PRECEDENCE)
* fun userAuthorization(): ServerHttpSecurityDsl.() -> Unit {
* // @formatter:off
* return {
* authorizeExchange {
* authorize("/user/profile", hasRole("USER"))
* }
* }
* // @formatter:on
* }
* ```
*/
private fun applyFunction1HttpSecurityDslBeans(context: ApplicationContext, http: ServerHttpSecurityDsl) : Unit {
val httpSecurityDslFnType = ResolvableType.forClassWithGenerics(Function1::class.java,
ServerHttpSecurityDsl::class.java, Unit::class.java)
val httpSecurityDslFnProvider = context
.getBeanProvider<Function1<ServerHttpSecurityDsl,Unit>>(httpSecurityDslFnType)
// @formatter:off
httpSecurityDslFnProvider.orderedStream().forEach { fn -> fn.invoke(http) }
// @formatter:on
}
/**
* Applies all `Function1<T,Unit>` Beans such that `T` is a top level
* DSL on `ServerHttpSecurityDsl`. This allows exposing the top level
* DSLs as Beans to be applied.
*
* ```
* @Bean
* fun headersSecurity(): Customizer<ServerHttpSecurity.HeaderSpec> {
* // @formatter:off
* return Customizer { headers -> headers
* .contentSecurityPolicy { csp -> csp
* .policyDirectives("object-src 'none'")
* }
* }
* // @formatter:on
* }
* ```
*
* @param context the [ApplicationContext]
* @param http the [HttpSecurity]
* @throws Exception
*/
private fun applyTopLevelFunction1SecurityDslBeans(context: ApplicationContext, http: ServerHttpSecurityDsl) {
val isCustomizerMethod = ReflectionUtils.MethodFilter { method: Method ->
if (Modifier.isStatic(method.modifiers)) {
return@MethodFilter false
}
if (!Modifier.isPublic(method.modifiers)) {
return@MethodFilter false
}
if (!method.canAccess(http)) {
return@MethodFilter false
}
if (method.parameterCount != 1) {
return@MethodFilter false
}
return@MethodFilter extractDslType(method) != null
}
val invokeWithEachDslBean = ReflectionUtils.MethodCallback { dslMethod: Method ->
val dslFunctionType = firstMethodResolvableType(dslMethod)!!
val dslFunctionProvider: ObjectProvider<*> = context.getBeanProvider<Any>(dslFunctionType)
// @formatter:off
dslFunctionProvider.orderedStream().forEach {customizer: Any -> ReflectionUtils.invokeMethod(dslMethod, http, customizer)}
}
ReflectionUtils.doWithMethods(ServerHttpSecurityDsl::class.java, invokeWithEachDslBean, isCustomizerMethod)
}
/**
* From a `Method` with the first argument `Function<T,Unit>` return `T` or `null`
* if the first argument is not a `Function`.
* @return From a `Method` with the first argument `Function<T,Unit>` return `T`.
*/
private fun extractDslType(method: Method): ResolvableType? {
val functionType = firstMethodResolvableType(method)
if (!Function::class.java.isAssignableFrom(functionType.toClass())) {
return null
}
val functionInputType = functionType.getGeneric(0)
val securityMarker = AnnotationUtils.findAnnotation(functionInputType.toClass(), ServerSecurityMarker::class.java)
val isSecurityDsl = securityMarker != null
if (!isSecurityDsl) {
return null
}
return functionInputType
}
private fun firstMethodResolvableType(method: Method): ResolvableType {
val parameter = MethodParameter(
method, 0
)
return ResolvableType.forMethodParameter(parameter)
}
/**
* Allows configuring the [ServerHttpSecurity] to only be invoked when matching the
* provided [ServerWebExchangeMatcher].

View File

@ -78,7 +78,6 @@ import org.springframework.security.authentication.jaas.event.JaasAuthentication
import org.springframework.security.authentication.jaas.event.JaasAuthenticationSuccessEvent;
import org.springframework.security.authentication.ott.DefaultOneTimeToken;
import org.springframework.security.authentication.ott.InvalidOneTimeTokenException;
import org.springframework.security.authentication.ott.OneTimeTokenAuthentication;
import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken;
import org.springframework.security.authentication.password.CompromisedPasswordException;
import org.springframework.security.authorization.AuthorityAuthorizationDecision;
@ -190,7 +189,6 @@ import org.springframework.security.saml2.provider.service.registration.OpenSaml
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import org.springframework.security.web.PortResolverImpl;
import org.springframework.security.web.authentication.AuthenticationFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException;
@ -402,8 +400,6 @@ final class SerializationSamples {
});
generatorByClassName.put(OneTimeTokenAuthenticationToken.class,
(r) -> applyDetails(new OneTimeTokenAuthenticationToken("username", "token")));
generatorByClassName.put(OneTimeTokenAuthentication.class,
(r) -> applyDetails(new OneTimeTokenAuthentication("username", authentication.getAuthorities())));
generatorByClassName.put(AccessDeniedException.class,
(r) -> new AccessDeniedException("access denied", new RuntimeException()));
generatorByClassName.put(AuthorizationServiceException.class,
@ -457,7 +453,7 @@ final class SerializationSamples {
generatorByClassName.put(AuthenticationSuccessEvent.class,
(r) -> new AuthenticationSuccessEvent(authentication));
generatorByClassName.put(InteractiveAuthenticationSuccessEvent.class,
(r) -> new InteractiveAuthenticationSuccessEvent(authentication, AuthenticationFilter.class));
(r) -> new InteractiveAuthenticationSuccessEvent(authentication, Authentication.class));
generatorByClassName.put(LogoutSuccessEvent.class, (r) -> new LogoutSuccessEvent(authentication));
generatorByClassName.put(JaasAuthenticationFailedEvent.class,
(r) -> new JaasAuthenticationFailedEvent(authentication, new RuntimeException("message")));

View File

@ -32,7 +32,6 @@ import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.SecurityAssertions;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.ObjectPostProcessor;
@ -45,6 +44,7 @@ import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@ -107,7 +107,8 @@ public class AuthenticationManagerBuilderTests {
.getAuthenticationManager();
Authentication auth = manager
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
SecurityAssertions.assertThat(auth).name("user").hasAuthority("ROLE_USER");
assertThat(auth.getName()).isEqualTo("user");
assertThat(auth.getAuthorities()).extracting(GrantedAuthority::getAuthority).containsOnly("ROLE_USER");
}
@Test
@ -118,7 +119,8 @@ public class AuthenticationManagerBuilderTests {
.getAuthenticationManager();
Authentication auth = manager
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
SecurityAssertions.assertThat(auth).name("user").hasAuthority("ROLE_USER");
assertThat(auth.getName()).isEqualTo("user");
assertThat(auth.getAuthorities()).extracting(GrantedAuthority::getAuthority).containsOnly("ROLE_USER");
}
@Test

View File

@ -33,7 +33,6 @@ import io.micrometer.observation.ObservationHandler;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.observation.ObservationTextPublisher;
import jakarta.annotation.security.DenyAll;
import jakarta.servlet.RequestDispatcher;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
@ -139,7 +138,6 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
@ -151,7 +149,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
@ -1282,19 +1279,6 @@ public class PrePostMethodSecurityConfigurationTests {
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
}
// gh-17761
@Test
void getWhenPostAuthorizeAuthenticationNameNotMatchThenNoExceptionExposedInRequest() throws Exception {
this.spring.register(WebMvcMethodSecurityConfig.class, BasicController.class).autowire();
// @formatter:off
MockHttpServletRequestBuilder requestWithUser = get("/authorized-person")
.param("name", "john")
.with(user("rob"));
// @formatter:on
this.mvc.perform(requestWithUser)
.andExpect(request().attribute(RequestDispatcher.ERROR_EXCEPTION, nullValue()));
}
@Test
void getWhenPostAuthorizeWithinServiceAuthenticationNameMatchesThenRespondsWithOk() throws Exception {
this.spring.register(WebMvcMethodSecurityConfig.class, BasicController.class, BasicService.class).autowire();

View File

@ -25,7 +25,6 @@ import javax.security.auth.login.LoginContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -311,7 +310,7 @@ public class NamespaceHttpTests {
}
@Override
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
public AuthorizationResult authorize(Supplier<Authentication> authentication,
RequestAuthorizationContext object) {
HttpServletRequest request = object.getRequest();
FilterInvocation invocation = new FilterInvocation(request.getContextPath(), request.getServletPath(),

View File

@ -28,20 +28,14 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.event.EventListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.access.AccessDeniedException;
@ -60,7 +54,6 @@ import org.springframework.security.config.annotation.SecurityContextChangedList
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
@ -89,15 +82,12 @@ import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.withSettings;
import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
@ -435,77 +425,6 @@ public class HttpSecurityConfigurationTests {
.andExpectAll(status().isFound(), redirectedUrl("/"), authenticated());
}
@Test
void authorizeHttpRequestsCustomizerBean() throws Exception {
this.spring.register(AuthorizeRequestsBeanConfiguration.class, UserDetailsConfig.class).autowire();
Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeRequests = this.spring
.getContext()
.getBean("authorizeRequests", Customizer.class);
verify(authorizeRequests).customize(any());
}
@Test
void multiAuthorizeHttpRequestsCustomizerBean() throws Exception {
this.spring.register(MultiAuthorizeRequestsBeanConfiguration.class, UserDetailsConfig.class).autowire();
Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeRequests0 = this.spring
.getContext()
.getBean("authorizeRequests0", Customizer.class);
Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeRequests = this.spring
.getContext()
.getBean("authorizeRequests", Customizer.class);
InOrder inOrder = Mockito.inOrder(authorizeRequests0, authorizeRequests);
ArgumentCaptor<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> arg0 = ArgumentCaptor
.forClass(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry.class);
ArgumentCaptor<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> arg1 = ArgumentCaptor
.forClass(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry.class);
inOrder.verify(authorizeRequests0).customize(arg0.capture());
inOrder.verify(authorizeRequests).customize(arg1.capture());
}
@Test
void disableAuthorizeHttpRequestsCustomizerBean() throws Exception {
this.spring.register(AuthorizeRequestsBeanConfiguration.class, UserDetailsConfig.class).autowire();
Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeRequests = this.spring
.getContext()
.getBean("authorizeRequests", Customizer.class);
verify(authorizeRequests).customize(any());
}
@Test
void httpSecurityCustomizerBean() throws Exception {
this.spring.register(HttpSecurityCustomizerBeanConfiguration.class, UserDetailsConfig.class).autowire();
Customizer<HttpSecurity> httpSecurityCustomizer = this.spring.getContext()
.getBean("httpSecurityCustomizer", Customizer.class);
ArgumentCaptor<HttpSecurity> arg0 = ArgumentCaptor.forClass(HttpSecurity.class);
verify(httpSecurityCustomizer).customize(arg0.capture());
}
@Test
void multiHttpSecurityCustomizerBean() throws Exception {
this.spring.register(MultiHttpSecurityCustomizerBeanConfiguration.class, UserDetailsConfig.class).autowire();
Customizer<HttpSecurity> httpSecurityCustomizer = this.spring.getContext()
.getBean("httpSecurityCustomizer", Customizer.class);
Customizer<HttpSecurity> httpSecurityCustomizer0 = this.spring.getContext()
.getBean("httpSecurityCustomizer0", Customizer.class);
InOrder inOrder = Mockito.inOrder(httpSecurityCustomizer0, httpSecurityCustomizer);
ArgumentCaptor<HttpSecurity> arg0 = ArgumentCaptor.forClass(HttpSecurity.class);
ArgumentCaptor<HttpSecurity> arg1 = ArgumentCaptor.forClass(HttpSecurity.class);
inOrder.verify(httpSecurityCustomizer0).customize(arg0.capture());
inOrder.verify(httpSecurityCustomizer).customize(arg1.capture());
}
@RestController
static class NameController {
@ -866,134 +785,6 @@ public class HttpSecurityConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableWebMvc
static class AuthorizeRequestsBeanConfiguration {
@Bean
SecurityFilterChain noAuthorizeSecurity(HttpSecurity http) throws Exception {
http.httpBasic(withDefaults());
return http.build();
}
@Bean
static Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeRequests()
throws Exception {
Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authz = mock(
Customizer.class, withSettings().name("authz"));
// prevent validation errors of no authorization rules being defined
willAnswer(((invocation) -> {
AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry requests = invocation
.getArgument(0);
requests.anyRequest().authenticated();
return null;
})).given(authz).customize(any());
return authz;
}
@RestController
static class PublicController {
@GetMapping("/public")
String permitAll() {
return "public";
}
}
}
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableWebMvc
static class DisableAuthorizeRequestsBeanConfiguration {
@Bean
SecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
http.httpBasic(withDefaults());
// @formatter:off
http.authorizeHttpRequests((requests) -> requests
.anyRequest().permitAll()
);
// @formatter:on
return http.build();
}
@Bean
static Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeRequests()
throws Exception {
// @formatter:off
return (requests) -> requests
.anyRequest().denyAll();
// @formatter:on
}
@RestController
static class PublicController {
@GetMapping("/public")
String permitAll() {
return "public";
}
}
}
@Configuration(proxyBeanMethods = false)
@Import(AuthorizeRequestsBeanConfiguration.class)
static class MultiAuthorizeRequestsBeanConfiguration {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
static Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeRequests0()
throws Exception {
return mock(Customizer.class, withSettings().name("authz0"));
}
}
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableWebMvc
static class HttpSecurityCustomizerBeanConfiguration {
@Bean
SecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
http.httpBasic(withDefaults());
return http.build();
}
@Bean
static Customizer<HttpSecurity> httpSecurityCustomizer() {
return mock(Customizer.class, withSettings().name("httpSecurityCustomizer"));
}
@RestController
static class PublicController {
@GetMapping("/public")
String permitAll() {
return "public";
}
}
}
@Configuration(proxyBeanMethods = false)
@Import(HttpSecurityCustomizerBeanConfiguration.class)
static class MultiHttpSecurityCustomizerBeanConfiguration {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
static Customizer<HttpSecurity> httpSecurityCustomizer0() throws Exception {
return mock(Customizer.class, withSettings().name("httpSecurityCustomizer0"));
}
}
private static class TestCompromisedPasswordChecker implements CompromisedPasswordChecker {
@Override

View File

@ -24,7 +24,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@ -35,7 +34,6 @@ import org.springframework.security.core.userdetails.AuthenticationUserDetailsSe
import org.springframework.security.core.userdetails.User;
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter;
import org.springframework.test.web.servlet.MockMvc;
@ -66,16 +64,18 @@ public class JeeConfigurerTests {
@Test
public void configureWhenRegisteringObjectPostProcessorThenInvokedOnJ2eePreAuthenticatedProcessingFilter() {
ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
this.spring.register(ObjectPostProcessorConfig.class).autowire();
ObjectPostProcessor<Object> objectPostProcessor = this.spring.getContext().getBean(ObjectPostProcessor.class);
verify(objectPostProcessor).postProcess(any(J2eePreAuthenticatedProcessingFilter.class));
verify(ObjectPostProcessorConfig.objectPostProcessor)
.postProcess(any(J2eePreAuthenticatedProcessingFilter.class));
}
@Test
public void configureWhenRegisteringObjectPostProcessorThenInvokedOnJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource() {
ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
this.spring.register(ObjectPostProcessorConfig.class).autowire();
ObjectPostProcessor<Object> objectPostProcessor = this.spring.getContext().getBean(ObjectPostProcessor.class);
verify(objectPostProcessor).postProcess(any(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class));
verify(ObjectPostProcessorConfig.objectPostProcessor)
.postProcess(any(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class));
}
@Test
@ -135,14 +135,12 @@ public class JeeConfigurerTests {
public void requestWhenCustomAuthenticatedUserDetailsServiceInLambdaThenCustomAuthenticatedUserDetailsServiceUsed()
throws Exception {
this.spring.register(JeeCustomAuthenticatedUserDetailsServiceConfig.class).autowire();
AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> userDetailsService = this.spring
.getContext()
.getBean(AuthenticationUserDetailsService.class);
Principal user = mock(Principal.class);
User userDetails = new User("user", "N/A", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_USER"));
given(user.getName()).willReturn("user");
given(userDetailsService.loadUserDetails(any())).willReturn(userDetails);
given(JeeCustomAuthenticatedUserDetailsServiceConfig.authenticationUserDetailsService.loadUserDetails(any()))
.willReturn(userDetails);
// @formatter:off
MockHttpServletRequestBuilder authRequest = get("/")
.principal(user)
@ -159,7 +157,7 @@ public class JeeConfigurerTests {
@EnableWebSecurity
static class ObjectPostProcessorConfig {
ObjectPostProcessor<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
static ObjectPostProcessor<Object> objectPostProcessor;
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
@ -171,9 +169,8 @@ public class JeeConfigurerTests {
}
@Bean
@Primary
ObjectPostProcessor<Object> objectPostProcessor() {
return this.objectPostProcessor;
static ObjectPostProcessor<Object> objectPostProcessor() {
return objectPostProcessor;
}
}
@ -248,7 +245,7 @@ public class JeeConfigurerTests {
@EnableWebSecurity
public static class JeeCustomAuthenticatedUserDetailsServiceConfig {
private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> authenticationUserDetailsService = mock(
static AuthenticationUserDetailsService authenticationUserDetailsService = mock(
AuthenticationUserDetailsService.class);
@Bean
@ -259,17 +256,12 @@ public class JeeConfigurerTests {
.anyRequest().hasRole("USER")
)
.jee((jee) -> jee
.authenticatedUserDetailsService(this.authenticationUserDetailsService)
.authenticatedUserDetailsService(authenticationUserDetailsService)
);
return http.build();
// @formatter:on
}
@Bean
AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> authenticationUserDetailsService() {
return this.authenticationUserDetailsService;
}
}
}

View File

@ -300,15 +300,7 @@ public class WebAuthnConfigurerTests {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.formLogin(Customizer.withDefaults())
.webAuthn((authn) -> authn
.rpId("spring.io")
.rpName("spring")
);
// @formatter:on
return http.build();
return http.formLogin(Customizer.withDefaults()).webAuthn(Customizer.withDefaults()).build();
}
}
@ -324,14 +316,7 @@ public class WebAuthnConfigurerTests {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.webAuthn((authn) -> authn
.rpId("spring.io")
.rpName("spring")
);
// @formatter:on
return http.build();
return http.webAuthn(Customizer.withDefaults()).build();
}
}
@ -347,16 +332,9 @@ public class WebAuthnConfigurerTests {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.formLogin(Customizer.withDefaults())
.webAuthn((authn) -> authn
.rpId("spring.io")
.rpName("spring")
.disableDefaultRegistrationPage(true)
);
// @formatter:on
return http.build();
return http.formLogin(Customizer.withDefaults())
.webAuthn((webauthn) -> webauthn.disableDefaultRegistrationPage(true))
.build();
}
}
@ -372,18 +350,9 @@ public class WebAuthnConfigurerTests {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.formLogin((login) -> login
.loginPage("/custom-login-page")
)
.webAuthn((authn) -> authn
.rpId("spring.io")
.rpName("spring")
.disableDefaultRegistrationPage(true)
);
// @formatter:on
return http.build();
return http.formLogin((login) -> login.loginPage("/custom-login-page"))
.webAuthn((webauthn) -> webauthn.disableDefaultRegistrationPage(true))
.build();
}
}

View File

@ -45,7 +45,6 @@ import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.SecurityAssertions;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.ObjectPostProcessor;
@ -218,9 +217,10 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication)
.hasAuthority("OAUTH2_USER")
.isInstanceOf(OAuth2UserAuthority.class);
assertThat(authentication.getAuthorities()).hasSize(1);
assertThat(authentication.getAuthorities()).first()
.isInstanceOf(OAuth2UserAuthority.class)
.hasToString("OAUTH2_USER");
}
@Test
@ -234,9 +234,10 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication)
.hasAuthority("OAUTH2_USER")
.isInstanceOf(OAuth2UserAuthority.class);
assertThat(authentication.getAuthorities()).hasSize(1);
assertThat(authentication.getAuthorities()).first()
.isInstanceOf(OAuth2UserAuthority.class)
.hasToString("OAUTH2_USER");
SecurityContextHolderStrategy strategy = this.context.getBean(SecurityContextHolderStrategy.class);
verify(strategy, atLeastOnce()).getDeferredContext();
SecurityContextChangedListener listener = this.context.getBean(SecurityContextChangedListener.class);
@ -254,9 +255,10 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication)
.hasAuthority("OAUTH2_USER")
.isInstanceOf(OAuth2UserAuthority.class);
assertThat(authentication.getAuthorities()).hasSize(1);
assertThat(authentication.getAuthorities()).first()
.isInstanceOf(OAuth2UserAuthority.class)
.hasToString("OAUTH2_USER");
}
// gh-6009
@ -294,7 +296,9 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication).hasAuthorities("OAUTH2_USER", "ROLE_OAUTH2_USER");
assertThat(authentication.getAuthorities()).hasSize(2);
assertThat(authentication.getAuthorities()).first().hasToString("OAUTH2_USER");
assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OAUTH2_USER");
}
@Test
@ -313,7 +317,9 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication).hasAuthorities("OAUTH2_USER", "ROLE_OAUTH2_USER");
assertThat(authentication.getAuthorities()).hasSize(2);
assertThat(authentication.getAuthorities()).first().hasToString("OAUTH2_USER");
assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OAUTH2_USER");
}
@Test
@ -332,7 +338,9 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication).hasAuthorities("OAUTH2_USER", "ROLE_OAUTH2_USER");
assertThat(authentication.getAuthorities()).hasSize(2);
assertThat(authentication.getAuthorities()).first().hasToString("OAUTH2_USER");
assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OAUTH2_USER");
}
// gh-5488
@ -353,9 +361,10 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication)
.hasAuthority("OAUTH2_USER")
.isInstanceOf(OAuth2UserAuthority.class);
assertThat(authentication.getAuthorities()).hasSize(1);
assertThat(authentication.getAuthorities()).first()
.isInstanceOf(OAuth2UserAuthority.class)
.hasToString("OAUTH2_USER");
}
// gh-5521
@ -561,7 +570,10 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication).hasAuthority("OIDC_USER").isInstanceOf(OidcUserAuthority.class);
assertThat(authentication.getAuthorities()).hasSize(1);
assertThat(authentication.getAuthorities()).first()
.isInstanceOf(OidcUserAuthority.class)
.hasToString("OIDC_USER");
}
@Test
@ -581,7 +593,9 @@ public class OAuth2LoginConfigurerTests {
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
assertThat(authentication.getAuthorities()).hasSize(1);
SecurityAssertions.assertThat(authentication).hasAuthority("OIDC_USER").isInstanceOf(OidcUserAuthority.class);
assertThat(authentication.getAuthorities()).first()
.isInstanceOf(OidcUserAuthority.class)
.hasToString("OIDC_USER");
}
@Test
@ -600,7 +614,9 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication).hasAuthorities("OIDC_USER", "ROLE_OIDC_USER");
assertThat(authentication.getAuthorities()).hasSize(2);
assertThat(authentication.getAuthorities()).first().hasToString("OIDC_USER");
assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OIDC_USER");
}
@Test
@ -619,7 +635,9 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication).hasAuthorities("OIDC_USER", "ROLE_OIDC_USER");
assertThat(authentication.getAuthorities()).hasSize(2);
assertThat(authentication.getAuthorities()).first().hasToString("OIDC_USER");
assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OIDC_USER");
}
@Test
@ -672,7 +690,11 @@ public class OAuth2LoginConfigurerTests {
Authentication authentication = this.securityContextRepository
.loadContext(new HttpRequestResponseHolder(this.request, this.response))
.getAuthentication();
SecurityAssertions.assertThat(authentication).hasAuthority("OIDC_USER").isInstanceOf(OidcUserAuthority.class);
assertThat(authentication.getAuthorities()).hasSize(1);
assertThat(authentication.getAuthorities()).first()
.isInstanceOf(OidcUserAuthority.class)
.hasToString("OIDC_USER");
// Ensure shared objects set for OAuth2 Client are not used
ClientRegistrationRepository clientRegistrationRepository = this.spring.getContext()
.getBean(ClientRegistrationRepository.class);

View File

@ -2674,7 +2674,6 @@ public class OAuth2ResourceServerConfigurerTests {
String requiresReadScope(JwtAuthenticationToken token) {
return token.getAuthorities()
.stream()
.filter((ga) -> ga.getAuthority().startsWith("SCOPE_"))
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList())
.toString();

View File

@ -29,17 +29,12 @@ import io.micrometer.observation.ObservationRegistry;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mockito;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.password.CompromisedPasswordDecision;
@ -51,7 +46,6 @@ import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity.AuthorizeExchangeSpec;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@ -273,47 +267,6 @@ public class ServerHttpSecurityConfigurationTests {
assertThat(contexts.next().getContextualName()).isEqualTo("security filterchain after");
}
@Test
void authorizeExchangeCustomizerBean() {
this.spring.register(AuthorizeExchangeCustomizerBeanConfig.class).autowire();
Customizer<AuthorizeExchangeSpec> authzCustomizer = this.spring.getContext().getBean("authz", Customizer.class);
ArgumentCaptor<AuthorizeExchangeSpec> arg0 = ArgumentCaptor.forClass(AuthorizeExchangeSpec.class);
verify(authzCustomizer).customize(arg0.capture());
}
@Test
void multiAuthorizeExchangeCustomizerBean() {
this.spring.register(MultiAuthorizeExchangeCustomizerBeanConfig.class).autowire();
Customizer<AuthorizeExchangeSpec> authzCustomizer = this.spring.getContext().getBean("authz", Customizer.class);
ArgumentCaptor<AuthorizeExchangeSpec> arg0 = ArgumentCaptor.forClass(AuthorizeExchangeSpec.class);
verify(authzCustomizer).customize(arg0.capture());
}
@Test
void serverHttpSecurityCustomizerBean() {
this.spring.register(ServerHttpSecurityCustomizerConfig.class).autowire();
Customizer<ServerHttpSecurity> httpSecurityCustomizer = this.spring.getContext()
.getBean("httpSecurityCustomizer", Customizer.class);
ArgumentCaptor<ServerHttpSecurity> arg0 = ArgumentCaptor.forClass(ServerHttpSecurity.class);
verify(httpSecurityCustomizer).customize(arg0.capture());
}
@Test
void multiServerHttpSecurityCustomizerBean() {
this.spring.register(MultiServerHttpSecurityCustomizerConfig.class).autowire();
Customizer<ServerHttpSecurity> httpSecurityCustomizer = this.spring.getContext()
.getBean("httpSecurityCustomizer", Customizer.class);
Customizer<ServerHttpSecurity> httpSecurityCustomizer0 = this.spring.getContext()
.getBean("httpSecurityCustomizer0", Customizer.class);
InOrder inOrder = Mockito.inOrder(httpSecurityCustomizer0, httpSecurityCustomizer);
ArgumentCaptor<ServerHttpSecurity> arg0 = ArgumentCaptor.forClass(ServerHttpSecurity.class);
inOrder.verify(httpSecurityCustomizer0).customize(arg0.capture());
inOrder.verify(httpSecurityCustomizer).customize(arg0.capture());
}
@Configuration
static class SubclassConfig extends ServerHttpSecurityConfiguration {
@ -521,64 +474,4 @@ public class ServerHttpSecurityConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
@EnableWebFlux
@EnableWebFluxSecurity
@Import(UserDetailsConfig.class)
static class AuthorizeExchangeCustomizerBeanConfig {
@Bean
SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
return http.build();
}
@Bean
static Customizer<AuthorizeExchangeSpec> authz() {
return mock(Customizer.class);
}
}
@Configuration(proxyBeanMethods = false)
@Import(AuthorizeExchangeCustomizerBeanConfig.class)
static class MultiAuthorizeExchangeCustomizerBeanConfig {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
Customizer<AuthorizeExchangeSpec> authz0() {
return mock(Customizer.class);
}
}
@Configuration(proxyBeanMethods = false)
@EnableWebFlux
@EnableWebFluxSecurity
@Import(UserDetailsConfig.class)
static class ServerHttpSecurityCustomizerConfig {
@Bean
SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
return http.build();
}
@Bean
static Customizer<ServerHttpSecurity> httpSecurityCustomizer() {
return mock(Customizer.class);
}
}
@Configuration(proxyBeanMethods = false)
@Import(ServerHttpSecurityCustomizerConfig.class)
static class MultiServerHttpSecurityCustomizerConfig {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
static Customizer<ServerHttpSecurity> httpSecurityCustomizer0() {
return mock(Customizer.class);
}
}
}

View File

@ -68,7 +68,7 @@ public class UserServiceBeanDefinitionParserTests {
System.setProperty("principal.pass", "joespassword");
System.setProperty("principal.authorities", "ROLE_A,ROLE_B");
// @formatter:off
setContext("<b:bean class='org.springframework.context.support.PropertySourcesPlaceholderConfigurer'/>"
setContext("<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
+ "<user-service id='service'>"
+ " <user name='${principal.name}' password='${principal.pass}' authorities='${principal.authorities}'/>"
+ "</user-service>");

View File

@ -92,7 +92,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
public void interceptUrlsSupportPropertyPlaceholders() {
System.setProperty("secure.url", "/secure");
System.setProperty("secure.role", "ROLE_A");
setContext("<b:bean class='org.springframework.context.support.PropertySourcesPlaceholderConfigurer'/>"
setContext("<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
+ "<filter-security-metadata-source id='fids' use-expressions='false'>"
+ " <intercept-url pattern='${secure.url}' access='${secure.role}'/>"
+ "</filter-security-metadata-source>");

View File

@ -24,11 +24,11 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@ -125,11 +125,11 @@ public class CustomHttpSecurityConfigurerTests {
}
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
// Typically externalize this as a properties file
Properties properties = new Properties();
properties.setProperty("permitAllPattern", "/public/**");
PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer();
propertyPlaceholderConfigurer.setProperties(properties);
return propertyPlaceholderConfigurer;
}
@ -153,11 +153,11 @@ public class CustomHttpSecurityConfigurerTests {
}
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
// Typically externalize this as a properties file
Properties properties = new Properties();
properties.setProperty("permitAllPattern", "/public/**");
PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer();
propertyPlaceholderConfigurer.setProperties(properties);
return propertyPlaceholderConfigurer;
}

View File

@ -464,9 +464,7 @@ public class MethodSecurityBeanDefinitionParserTests {
static class MyAuthorizationManager implements AuthorizationManager<MethodInvocation> {
@Override
public AuthorizationResult authorize(
Supplier<? extends @org.jspecify.annotations.Nullable Authentication> authentication,
MethodInvocation object) {
public AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation object) {
return new AuthorizationDecision("bob".equals(authentication.get().getName()));
}

View File

@ -30,11 +30,8 @@ import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostP
import org.springframework.mock.web.MockServletConfig;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.util.InMemoryXmlWebApplicationContext;
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers;
import org.springframework.security.test.web.reactive.server.WebTestClientBuilder;
import org.springframework.security.web.servlet.MockServletContext;
import org.springframework.test.context.web.GenericXmlWebContextLoader;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
@ -45,7 +42,6 @@ import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.server.WebFilter;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
@ -160,18 +156,6 @@ public class SpringTestContext implements Closeable {
// @formatter:on
this.context.getBeanFactory().registerResolvableDependency(MockMvc.class, mockMvc);
}
String webFluxSecurityBean = "org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration.WebFilterChainFilter";
if (this.context.containsBean(webFluxSecurityBean)) {
WebFilter springSecurityFilter = this.context.getBean(webFluxSecurityBean, WebFilter.class);
// @formatter:off
WebTestClient webTest = WebTestClient
.bindToController(new WebTestClientBuilder.Http200RestController())
.webFilter(springSecurityFilter)
.apply(SecurityMockServerConfigurers.springSecurity())
.build();
// @formatter:on
this.context.getBeanFactory().registerResolvableDependency(WebTestClient.class, webTest);
}
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(this.context.getBeanFactory());
bpp.processInjection(this.test);

View File

@ -16,27 +16,18 @@
package org.springframework.security.config.web.server;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import reactor.core.publisher.Mono;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.web.reactive.ServerHttpSecurityConfigurationBuilder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.htmlunit.server.WebTestClientHtmlUnitDriverBuilder;
import org.springframework.security.test.web.reactive.server.WebTestClientBuilder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.logout.ServerLogoutHandler;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.security.config.Customizer.withDefaults;
@ -219,84 +210,6 @@ public class LogoutSpecTests {
FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class).assertAt();
}
@Test
public void multipleLogoutHandlers() {
InMemorySecurityContextRepository repository = new InMemorySecurityContextRepository();
MultiValueMap<String, String> logoutData = new LinkedMultiValueMap<>();
ServerLogoutHandler handler1 = (exchange, authentication) -> {
logoutData.add("handler-header", "value1");
return Mono.empty();
};
ServerLogoutHandler handler2 = (exchange, authentication) -> {
logoutData.add("handler-header", "value2");
return Mono.empty();
};
// @formatter:off
SecurityWebFilterChain securityWebFilter = this.http
.securityContextRepository(repository)
.authorizeExchange((authorize) -> authorize
.anyExchange().authenticated())
.formLogin(withDefaults())
.logout((logoutSpec) -> logoutSpec.logoutHandler((handlers) -> {
handlers.add(handler1);
handlers.add(0, handler2);
}))
.build();
WebTestClient webTestClient = WebTestClientBuilder
.bindToWebFilters(securityWebFilter)
.build();
WebDriver driver = WebTestClientHtmlUnitDriverBuilder
.webTestClientSetup(webTestClient)
.build();
// @formatter:on
FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage
.to(driver, FormLoginTests.DefaultLoginPage.class)
.assertAt();
// @formatter:off
loginPage = loginPage.loginForm()
.username("user")
.password("invalid")
.submit(FormLoginTests.DefaultLoginPage.class)
.assertError();
FormLoginTests.HomePage homePage = loginPage.loginForm()
.username("user")
.password("password")
.submit(FormLoginTests.HomePage.class);
// @formatter:on
homePage.assertAt();
SecurityContext savedContext = repository.getSavedContext();
assertThat(savedContext).isNotNull();
assertThat(savedContext.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class);
loginPage = FormLoginTests.DefaultLogoutPage.to(driver).assertAt().logout();
loginPage.assertAt().assertLogout();
assertThat(logoutData).hasSize(1);
assertThat(logoutData.get("handler-header")).containsExactly("value2", "value1");
savedContext = repository.getSavedContext();
assertThat(savedContext).isNull();
}
private static class InMemorySecurityContextRepository implements ServerSecurityContextRepository {
@Nullable private SecurityContext savedContext;
@Override
public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
this.savedContext = context;
return Mono.empty();
}
@Override
public Mono<SecurityContext> load(ServerWebExchange exchange) {
return Mono.justOrEmpty(this.savedContext);
}
@Nullable private SecurityContext getSavedContext() {
return this.savedContext;
}
}
@RestController
public static class HomeController {

View File

@ -26,7 +26,6 @@ import java.util.Map;
import java.util.function.Supplier;
import org.assertj.core.api.ThrowableAssert;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -736,7 +735,7 @@ public class WebSocketMessageBrokerConfigTests {
}
@Override
public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
Message<Object> message) {
return new StandardEvaluationContext(new MessageSecurityExpressionRoot(authentication, message) {
public boolean denyNile() {

View File

@ -193,7 +193,7 @@ class AuthorizeHttpRequestsDslTests {
open class MvcMatcherPathVariablesConfig {
@Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
val access = AuthorizationManager { _: Supplier<out Authentication>, context: RequestAuthorizationContext ->
val access = AuthorizationManager { _: Supplier<Authentication>, context: RequestAuthorizationContext ->
AuthorizationDecision(context.variables["userName"] == "user")
}
http {

View File

@ -367,7 +367,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Filter>? = filterChain.getFilters("/")
val filters: List<Filter> = filterChain.getFilters("/")
assertThat(filters).anyMatch { it is CustomFilter }
}
@ -390,7 +390,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterConfigReified::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Filter>? = filterChain.getFilters("/")
val filters: List<Filter> = filterChain.getFilters("/")
assertThat(filters).anyMatch { it is CustomFilter }
}
@ -413,7 +413,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterAfterConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
val filters: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
assertThat(filters).containsSubsequence(
UsernamePasswordAuthenticationFilter::class.java,
@ -440,7 +440,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterAfterConfigReified::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
assertThat(filterClasses).containsSubsequence(
UsernamePasswordAuthenticationFilter::class.java,
@ -467,7 +467,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterBeforeConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
val filters: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
assertThat(filters).containsSubsequence(
CustomFilter::class.java,
@ -494,7 +494,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterBeforeConfigReified::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
assertThat(filterClasses).containsSubsequence(
CustomFilter::class.java,
@ -523,7 +523,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomSecurityConfigurerConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
assertThat(filterClasses).contains(
CustomFilter::class.java
@ -535,7 +535,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomSecurityConfigurerConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
assertThat(filterClasses).contains(
CustomFilter::class.java
@ -588,7 +588,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomDslUsingWithConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
assertThat(filterClasses).contains(
UsernamePasswordAuthenticationFilter::class.java
@ -623,38 +623,5 @@ class HttpSecurityDslTests {
}
@Test
fun `HTTP security when Dsl Bean`() {
this.spring.register(DslBeanConfig::class.java).autowire()
this.mockMvc.get("/")
.andExpect {
header {
string("Content-Security-Policy", "object-src 'none'")
}
}
}
@Configuration
@EnableWebSecurity
@EnableWebMvc
open class DslBeanConfig {
@Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
httpBasic { }
}
return http.build()
}
@Bean
open fun headersDsl(): HeadersDsl.() -> Unit {
return {
contentSecurityPolicy {
policyDirectives = "object-src 'none'"
}
}
}
}
}

View File

@ -350,8 +350,8 @@ class LogoutDslTests {
class NoopLogoutHandler: LogoutHandler {
override fun logout(
request: HttpServletRequest,
response: HttpServletResponse,
request: HttpServletRequest?,
response: HttpServletResponse?,
authentication: Authentication?
) { }

View File

@ -22,6 +22,7 @@ import io.mockk.mockk
import io.mockk.verify
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
@ -43,6 +44,7 @@ import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequ
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
import org.springframework.security.web.authentication.ott.DefaultGenerateOneTimeTokenRequestResolver
import org.springframework.security.web.authentication.ott.GenerateOneTimeTokenRequestResolver
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler
@ -51,6 +53,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers
import java.time.Duration
import java.time.Instant
import java.time.ZoneOffset
/**
* Tests for [OneTimeTokenLoginDsl]
@ -264,7 +267,7 @@ class OneTimeTokenLoginDslTests {
)
}
constructor(redirectUrl: String) {
constructor(redirectUrl: String?) {
this.delegate =
RedirectOneTimeTokenGenerationSuccessHandler(
redirectUrl

View File

@ -132,8 +132,8 @@ class RequiresChannelDslTests {
companion object {
val CHANNEL_PROCESSOR: ChannelProcessor = object : ChannelProcessor {
override fun decide(invocation: FilterInvocation, config: MutableCollection<ConfigAttribute>) {}
override fun supports(attribute: ConfigAttribute): Boolean = true
override fun decide(invocation: FilterInvocation?, config: MutableCollection<ConfigAttribute>?) {}
override fun supports(attribute: ConfigAttribute?): Boolean = true
}
}

View File

@ -93,7 +93,7 @@ class SecurityContextDslTests {
testContext.autowire()
val filterChainProxy = testContext.context.getBean(FilterChainProxy::class.java)
// @formatter:off
val filterTypes = filterChainProxy.getFilters("/")!!.toList()
val filterTypes = filterChainProxy.getFilters("/").toList()
assertThat(filterTypes)
.anyMatch { it is SecurityContextHolderFilter }

View File

@ -1,5 +1,4 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -126,8 +125,6 @@ class WebAuthnDslTests {
http{
formLogin { }
webAuthn {
rpId = "spring.io"
rpName = "spring"
disableDefaultRegistrationPage = true
}
}
@ -147,10 +144,7 @@ class WebAuthnDslTests {
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http{
formLogin { }
webAuthn {
rpId = "spring.io"
rpName = "spring"
}
webAuthn { }
}
return http.build()
}

View File

@ -270,8 +270,8 @@ class ServerHttpBasicDslTests {
open class MockServerAuthenticationFailureHandler: ServerAuthenticationFailureHandler {
override fun onAuthenticationFailure(
webFilterExchange: WebFilterExchange,
exception: AuthenticationException
webFilterExchange: WebFilterExchange?,
exception: AuthenticationException?
): Mono<Void> {
return Mono.empty()
}

View File

@ -175,8 +175,8 @@ class ServerOAuth2ResourceServerDslTests {
open class MockServerAuthenticationFailureHandler: ServerAuthenticationFailureHandler {
override fun onAuthenticationFailure(
webFilterExchange: WebFilterExchange,
exception: AuthenticationException
webFilterExchange: WebFilterExchange?,
exception: AuthenticationException?
): Mono<Void> {
return Mono.empty()
}

View File

@ -280,11 +280,11 @@ class ServerOneTimeTokenLoginDslTests {
this.delegate = ServerRedirectOneTimeTokenGenerationSuccessHandler("/login/ott")
}
constructor(redirectUrl: String) {
constructor(redirectUrl: String?) {
this.delegate = ServerRedirectOneTimeTokenGenerationSuccessHandler(redirectUrl)
}
override fun handle(exchange: ServerWebExchange, oneTimeToken: OneTimeToken): Mono<Void> {
override fun handle(exchange: ServerWebExchange?, oneTimeToken: OneTimeToken?): Mono<Void> {
lastToken = oneTimeToken
return delegate!!.handle(exchange, oneTimeToken)
}

View File

@ -29,7 +29,7 @@
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>

View File

@ -29,7 +29,7 @@
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>

View File

@ -31,7 +31,7 @@
<custom-filter ref="userFilter" after="LOGOUT_FILTER"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="userFilter" class="org.mockito.Mockito" factory-method="mock">
<b:constructor-arg value="jakarta.servlet.Filter" type="java.lang.Class"/>

View File

@ -29,7 +29,7 @@
<intercept-url pattern="/**" access="authenticated"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:import resource="MiscHttpConfigTests-controllers.xml"/>
<b:import resource="userservice.xml"/>

View File

@ -35,7 +35,7 @@
</b:constructor-arg>
</b:bean>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:import resource="MiscHttpConfigTests-controllers.xml"/>
<b:import resource="userservice.xml"/>

View File

@ -29,7 +29,7 @@
<access-denied-handler error-page="${accessDenied}"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="sc" class="org.springframework.security.config.http.PlaceHolderAndELConfigTests.SimpleController"/>

View File

@ -29,7 +29,7 @@
<access-denied-handler error-page="#{'/go' + '-away'}"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="sc" class="org.springframework.security.config.http.PlaceHolderAndELConfigTests.SimpleController"/>

View File

@ -34,7 +34,7 @@
<csrf disabled="true"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="unsecured" class="org.springframework.security.config.http.PlaceHolderAndELConfigTests.SimpleController"/>

View File

@ -37,7 +37,7 @@
<csrf disabled="true"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="sc" class="org.springframework.security.config.http.PlaceHolderAndELConfigTests.SimpleController"/>

View File

@ -33,7 +33,7 @@
</port-mappings>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="sc" class="org.springframework.security.config.http.PlaceHolderAndELConfigTests.SimpleController"/>

View File

@ -28,7 +28,7 @@
<intercept-url pattern="${secure.url}" access="ROLE_USER" requires-channel="${required.channel}"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="sc" class="org.springframework.security.config.http.PlaceHolderAndELConfigTests.SimpleController"/>

View File

@ -30,7 +30,7 @@
<intercept-url pattern="/**" access="ROLE_NUNYA"/>
</http>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<b:bean name="unsecured" class="org.springframework.security.config.http.PlaceHolderAndELConfigTests.SimpleController"/>

View File

@ -31,7 +31,7 @@
token-validity-seconds="${security.rememberme.ttl}"/>
</http>
<b:bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<b:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<b:property name="properties" value="security.rememberme.ttl=30"/>
</b:bean>

View File

@ -28,7 +28,7 @@
<b:bean name="transactionManager" class="org.springframework.security.config.MockTransactionManager" />
<b:bean class='org.springframework.context.support.PropertySourcesPlaceholderConfigurer'/>
<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>
<b:bean id="transactionalTarget" class="org.springframework.security.config.TransactionalTestBusinessBean">
<intercept-methods use-authorization-manager="false">

View File

@ -110,7 +110,7 @@
</sec:filter-chain-map>
</bean>
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
<bean id="sec1235FilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>

View File

@ -18,8 +18,6 @@ package org.springframework.security.access;
import java.io.Serializable;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.security.access.intercept.RunAsManager;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
@ -47,7 +45,6 @@ import org.springframework.security.core.annotation.SecurityAnnotationScanner;
* {@link AuthorizationManager}.
*/
@Deprecated
@NullUnmarked
public interface ConfigAttribute extends Serializable {
/**

View File

@ -70,7 +70,7 @@ public abstract class AbstractSecurityExpressionHandler<T>
* suitable root object.
*/
@Override
public final EvaluationContext createEvaluationContext(@Nullable Authentication authentication, T invocation) {
public final EvaluationContext createEvaluationContext(Authentication authentication, T invocation) {
SecurityExpressionOperations root = createSecurityExpressionRoot(authentication, invocation);
StandardEvaluationContext ctx = createEvaluationContextInternal(authentication, invocation);
if (this.beanResolver != null) {
@ -91,8 +91,7 @@ public abstract class AbstractSecurityExpressionHandler<T>
* @return A {@code StandardEvaluationContext} or potentially a custom subclass if
* overridden.
*/
protected StandardEvaluationContext createEvaluationContextInternal(@Nullable Authentication authentication,
T invocation) {
protected StandardEvaluationContext createEvaluationContextInternal(Authentication authentication, T invocation) {
return new StandardEvaluationContext();
}
@ -103,8 +102,8 @@ public abstract class AbstractSecurityExpressionHandler<T>
* @param invocation the invocation (filter, method, channel)
* @return the object
*/
protected abstract SecurityExpressionOperations createSecurityExpressionRoot(
@Nullable Authentication authentication, T invocation);
protected abstract SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
T invocation);
protected @Nullable RoleHierarchy getRoleHierarchy() {
return this.roleHierarchy;

View File

@ -18,8 +18,6 @@ package org.springframework.security.access.expression;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
@ -44,7 +42,7 @@ public interface SecurityExpressionHandler<T> extends AopInfrastructureBean {
* Provides an evaluation context in which to evaluate security expressions for the
* invocation type.
*/
EvaluationContext createEvaluationContext(@Nullable Authentication authentication, T invocation);
EvaluationContext createEvaluationContext(Authentication authentication, T invocation);
/**
* Provides an evaluation context in which to evaluate security expressions for the
@ -57,8 +55,7 @@ public interface SecurityExpressionHandler<T> extends AopInfrastructureBean {
* @return the {@link EvaluationContext} to use
* @since 5.8
*/
default EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
T invocation) {
default EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, T invocation) {
return createEvaluationContext(authentication.get(), invocation);
}

View File

@ -78,7 +78,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
* Creates a new instance
* @param authentication the {@link Authentication} to use. Cannot be null.
*/
public SecurityExpressionRoot(@Nullable Authentication authentication) {
public SecurityExpressionRoot(Authentication authentication) {
this(() -> authentication);
}
@ -89,7 +89,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
* Cannot be null.
* @since 5.8
*/
public SecurityExpressionRoot(Supplier<? extends @Nullable Authentication> authentication) {
public SecurityExpressionRoot(Supplier<Authentication> authentication) {
this.authentication = SingletonSupplier.of(() -> {
Authentication value = authentication.get();
Assert.notNull(value, "Authentication object cannot be null");
@ -177,7 +177,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
this.trustResolver = trustResolver;
}
public void setRoleHierarchy(@Nullable RoleHierarchy roleHierarchy) {
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
this.roleHierarchy = roleHierarchy;
}

View File

@ -79,15 +79,12 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
* implementation.
*/
@Override
public StandardEvaluationContext createEvaluationContextInternal(@Nullable Authentication auth,
MethodInvocation mi) {
public StandardEvaluationContext createEvaluationContextInternal(Authentication auth, MethodInvocation mi) {
return new MethodSecurityEvaluationContext(auth, mi, getParameterNameDiscoverer());
}
@Override
@SuppressWarnings("NullAway") // FIXME: Dataflow analysis limitation
public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
MethodInvocation mi) {
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, MethodInvocation mi) {
MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(root, mi,
getParameterNameDiscoverer());
@ -99,13 +96,13 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
* Creates the root object for expression evaluation.
*/
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(@Nullable Authentication authentication,
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
MethodInvocation invocation) {
return createSecurityExpressionRoot(() -> authentication, invocation);
}
private MethodSecurityExpressionOperations createSecurityExpressionRoot(
Supplier<? extends @Nullable Authentication> authentication, MethodInvocation invocation) {
private MethodSecurityExpressionOperations createSecurityExpressionRoot(Supplier<Authentication> authentication,
MethodInvocation invocation) {
MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
root.setThis(invocation.getThis());
root.setPermissionEvaluator(getPermissionEvaluator());

View File

@ -38,11 +38,11 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements Met
private @Nullable Object target;
MethodSecurityExpressionRoot(@Nullable Authentication a) {
MethodSecurityExpressionRoot(Authentication a) {
super(a);
}
MethodSecurityExpressionRoot(Supplier<? extends @Nullable Authentication> authentication) {
MethodSecurityExpressionRoot(Supplier<Authentication> authentication) {
super(authentication);
}

View File

@ -18,8 +18,6 @@ package org.springframework.security.access.vote;
import java.util.Collection;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
@ -55,7 +53,6 @@ import org.springframework.security.core.GrantedAuthority;
* instead
*/
@Deprecated
@NullUnmarked
public class RoleVoter implements AccessDecisionVoter<Object> {
private String rolePrefix = "ROLE_";

View File

@ -16,9 +16,6 @@
package org.springframework.security.authentication;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Contract;
import org.springframework.security.core.Authentication;
/**
@ -40,7 +37,7 @@ public interface AuthenticationTrustResolver {
* @return <code>true</code> the passed authentication token represented an anonymous
* principal, <code>false</code> otherwise
*/
boolean isAnonymous(@Nullable Authentication authentication);
boolean isAnonymous(Authentication authentication);
/**
* Indicates whether the passed <code>Authentication</code> token represents user that
@ -54,7 +51,7 @@ public interface AuthenticationTrustResolver {
* @return <code>true</code> the passed authentication token represented a principal
* authenticated using a remember-me token, <code>false</code> otherwise
*/
boolean isRememberMe(@Nullable Authentication authentication);
boolean isRememberMe(Authentication authentication);
/**
* Indicates whether the passed <code>Authentication</code> token represents a fully
@ -69,7 +66,7 @@ public interface AuthenticationTrustResolver {
* {@link #isRememberMe(Authentication)}, <code>false</code> otherwise
* @since 6.1
*/
default boolean isFullyAuthenticated(@Nullable Authentication authentication) {
default boolean isFullyAuthenticated(Authentication authentication) {
return isAuthenticated(authentication) && !isRememberMe(authentication);
}
@ -81,8 +78,7 @@ public interface AuthenticationTrustResolver {
* {@link Authentication#isAuthenticated()} is true.
* @since 6.1.7
*/
@Contract("null -> false")
default boolean isAuthenticated(@Nullable Authentication authentication) {
default boolean isAuthenticated(Authentication authentication) {
return authentication != null && authentication.isAuthenticated() && !isAnonymous(authentication);
}

View File

@ -16,8 +16,6 @@
package org.springframework.security.authentication;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication;
/**
@ -46,7 +44,7 @@ public class AuthenticationTrustResolverImpl implements AuthenticationTrustResol
}
@Override
public boolean isAnonymous(@Nullable Authentication authentication) {
public boolean isAnonymous(Authentication authentication) {
if ((this.anonymousClass == null) || (authentication == null)) {
return false;
}
@ -54,7 +52,7 @@ public class AuthenticationTrustResolverImpl implements AuthenticationTrustResol
}
@Override
public boolean isRememberMe(@Nullable Authentication authentication) {
public boolean isRememberMe(Authentication authentication) {
if ((this.rememberMeClass == null) || (authentication == null)) {
return false;
}

View File

@ -18,8 +18,6 @@ package org.springframework.security.authentication;
import java.io.Serial;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.AuthenticationException;
/**
@ -37,7 +35,7 @@ public class BadCredentialsException extends AuthenticationException {
* Constructs a <code>BadCredentialsException</code> with the specified message.
* @param msg the detail message
*/
public BadCredentialsException(@Nullable String msg) {
public BadCredentialsException(String msg) {
super(msg);
}
@ -47,7 +45,7 @@ public class BadCredentialsException extends AuthenticationException {
* @param msg the detail message
* @param cause root cause
*/
public BadCredentialsException(@Nullable String msg, Throwable cause) {
public BadCredentialsException(String msg, Throwable cause) {
super(msg, cause);
}

View File

@ -39,7 +39,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
private static final long serialVersionUID = 620L;
private final @Nullable Object principal;
private final Object principal;
private @Nullable Object credentials;
@ -49,7 +49,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
* will return <code>false</code>.
*
*/
public UsernamePasswordAuthenticationToken(@Nullable Object principal, @Nullable Object credentials) {
public UsernamePasswordAuthenticationToken(Object principal, @Nullable Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
@ -82,8 +82,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
*
* @since 5.7
*/
public static UsernamePasswordAuthenticationToken unauthenticated(@Nullable Object principal,
@Nullable Object credentials) {
public static UsernamePasswordAuthenticationToken unauthenticated(Object principal, @Nullable Object credentials) {
return new UsernamePasswordAuthenticationToken(principal, credentials);
}
@ -107,7 +106,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
}
@Override
public @Nullable Object getPrincipal() {
public Object getPrincipal() {
return this.principal;
}

View File

@ -178,10 +178,8 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
// applied.
authorities = getAuthorities(principals);
// Convert the authorities set back to an array and apply it to the token.
Object principal = request.getPrincipal();
Assert.notNull(principal, "The principal cannot be null");
JaasAuthenticationToken result = new JaasAuthenticationToken(principal, request.getCredentials(),
new ArrayList<>(authorities), loginContext);
JaasAuthenticationToken result = new JaasAuthenticationToken(request.getPrincipal(),
request.getCredentials(), new ArrayList<>(authorities), loginContext);
// Publish the success event
publishSuccessEvent(result);
// we're done, return the token.

View File

@ -1,56 +0,0 @@
/*
* Copyright 2004-present 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.authentication.ott;
import java.io.Serial;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
/**
* The result of a successful one-time-token authentication
*
* @author Josh Cummings
* @since 7.0
*/
public class OneTimeTokenAuthentication extends AbstractAuthenticationToken {
@Serial
private static final long serialVersionUID = 1195893764725073959L;
private final Object principal;
public OneTimeTokenAuthentication(Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
setAuthenticated(true);
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public @Nullable Object getCredentials() {
return null;
}
}

View File

@ -56,7 +56,8 @@ public final class OneTimeTokenAuthenticationProvider implements AuthenticationP
}
try {
UserDetails user = this.userDetailsService.loadUserByUsername(consumed.getUsername());
OneTimeTokenAuthentication authenticated = new OneTimeTokenAuthentication(user, user.getAuthorities());
OneTimeTokenAuthenticationToken authenticated = OneTimeTokenAuthenticationToken.authenticated(user,
user.getAuthorities());
authenticated.setDetails(otpAuthenticationToken.getDetails());
return authenticated;
}

View File

@ -40,10 +40,6 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
private @Nullable String tokenValue;
/**
* @deprecated Please use constructor that takes a {@link String} instead
*/
@Deprecated(forRemoval = true, since = "7.0")
public OneTimeTokenAuthenticationToken(@Nullable Object principal, String tokenValue) {
super(Collections.emptyList());
this.tokenValue = tokenValue;
@ -54,10 +50,6 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
this(null, tokenValue);
}
/**
* @deprecated Please use {@link OneTimeTokenAuthentication} instead
*/
@Deprecated(forRemoval = true, since = "7.0")
public OneTimeTokenAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
@ -68,11 +60,9 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
* Creates an unauthenticated token
* @param tokenValue the one-time token value
* @return an unauthenticated {@link OneTimeTokenAuthenticationToken}
* @deprecated Please use constructor that takes a {@link String} instead
*/
@Deprecated(forRemoval = true, since = "7.0")
public static OneTimeTokenAuthenticationToken unauthenticated(@Nullable String tokenValue) {
return new OneTimeTokenAuthenticationToken(null, (tokenValue != null) ? tokenValue : "");
public static OneTimeTokenAuthenticationToken unauthenticated(String tokenValue) {
return new OneTimeTokenAuthenticationToken(null, tokenValue);
}
/**
@ -80,9 +70,7 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
* @param principal the principal
* @param tokenValue the one-time token value
* @return an unauthenticated {@link OneTimeTokenAuthenticationToken}
* @deprecated Please use constructor that takes a {@link String} instead
*/
@Deprecated(forRemoval = true, since = "7.0")
public static OneTimeTokenAuthenticationToken unauthenticated(Object principal, String tokenValue) {
return new OneTimeTokenAuthenticationToken(principal, tokenValue);
}
@ -92,9 +80,7 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
* @param principal the principal
* @param authorities the principal authorities
* @return an authenticated {@link OneTimeTokenAuthenticationToken}
* @deprecated Please use {@link OneTimeTokenAuthentication} instead
*/
@Deprecated(forRemoval = true, since = "7.0")
public static OneTimeTokenAuthenticationToken authenticated(Object principal,
Collection<? extends GrantedAuthority> authorities) {
return new OneTimeTokenAuthenticationToken(principal, authorities);

Some files were not shown because too many files have changed in this diff Show More