mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-10-22 10:18:53 +00:00
Enable Null checking in spring-security-test via JSpecify
Closes gh-17840
This commit is contained in:
parent
194be8ffb6
commit
6a84f96930
@ -1,3 +1,7 @@
|
||||
plugins {
|
||||
id 'security-nullability'
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
|
||||
dependencies {
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.test.aot.hint;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.MemberCategory;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
@ -36,7 +38,7 @@ import org.springframework.util.ClassUtils;
|
||||
class WebTestUtilsRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
if (!ClassUtils.isPresent("jakarta.servlet.Filter", classLoader)) {
|
||||
return;
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AOT Support for Spring Security test.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.aot.hint;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for Framework's Test annotations.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.context.annotation;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Security support managing the
|
||||
* {@link org.springframework.security.core.context.SecurityContext}.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.context;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -20,6 +20,9 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
@ -76,6 +79,7 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
|
||||
* {@link WithSecurityContext} on it. If that is not found, the class is inspected. If
|
||||
* still not found, then no {@link SecurityContext} is populated.
|
||||
*/
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void beforeTestMethod(TestContext testContext) {
|
||||
TestSecurityContext testSecurityContext = createTestSecurityContext(testContext.getTestMethod(), testContext);
|
||||
@ -98,6 +102,7 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
|
||||
* If configured before test execution sets the SecurityContext
|
||||
* @since 5.1
|
||||
*/
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void beforeTestExecution(TestContext testContext) {
|
||||
Supplier<SecurityContext> supplier = (Supplier<SecurityContext>) testContext
|
||||
@ -107,13 +112,13 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
|
||||
}
|
||||
}
|
||||
|
||||
private TestSecurityContext createTestSecurityContext(AnnotatedElement annotated, TestContext context) {
|
||||
private @Nullable TestSecurityContext createTestSecurityContext(AnnotatedElement annotated, TestContext context) {
|
||||
WithSecurityContext withSecurityContext = AnnotatedElementUtils.findMergedAnnotation(annotated,
|
||||
WithSecurityContext.class);
|
||||
return createTestSecurityContext(annotated, withSecurityContext, context);
|
||||
}
|
||||
|
||||
private TestSecurityContext createTestSecurityContext(Class<?> annotated, TestContext context) {
|
||||
private @Nullable TestSecurityContext createTestSecurityContext(Class<?> annotated, TestContext context) {
|
||||
TestContextAnnotationUtils.AnnotationDescriptor<WithSecurityContext> withSecurityContextDescriptor = TestContextAnnotationUtils
|
||||
.findAnnotationDescriptor(annotated, WithSecurityContext.class);
|
||||
if (withSecurityContextDescriptor == null) {
|
||||
@ -124,9 +129,10 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
|
||||
return createTestSecurityContext(rootDeclaringClass, withSecurityContext, context);
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private TestSecurityContext createTestSecurityContext(AnnotatedElement annotated,
|
||||
WithSecurityContext withSecurityContext, TestContext context) {
|
||||
private @Nullable TestSecurityContext createTestSecurityContext(AnnotatedElement annotated,
|
||||
@Nullable WithSecurityContext withSecurityContext, TestContext context) {
|
||||
if (withSecurityContext == null) {
|
||||
return null;
|
||||
}
|
||||
@ -147,7 +153,9 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
|
||||
return new TestSecurityContext(supplier, initialize);
|
||||
}
|
||||
|
||||
private Annotation findAnnotation(AnnotatedElement annotated, Class<? extends Annotation> type) {
|
||||
@NullUnmarked
|
||||
private @Nullable Annotation findAnnotation(AnnotatedElement annotated,
|
||||
@Nullable Class<? extends Annotation> type) {
|
||||
Annotation findAnnotation = AnnotatedElementUtils.findMergedAnnotation(annotated, type);
|
||||
if (findAnnotation != null) {
|
||||
return findAnnotation;
|
||||
@ -181,6 +189,7 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
|
||||
* Clears out the {@link TestSecurityContextHolder} and the
|
||||
* {@link SecurityContextHolder} after each test method.
|
||||
*/
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void afterTestMethod(TestContext testContext) {
|
||||
this.securityContextHolderStrategyConverter.convert(testContext).clearContext();
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.test.context.support;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
@ -89,7 +91,7 @@ final class WithUserDetailsSecurityContextFactory implements WithSecurityContext
|
||||
: this.beans.getBean(UserDetailsService.class);
|
||||
}
|
||||
|
||||
UserDetailsService findAndAdaptReactiveUserDetailsService(String beanName) {
|
||||
@Nullable UserDetailsService findAndAdaptReactiveUserDetailsService(String beanName) {
|
||||
try {
|
||||
ReactiveUserDetailsService reactiveUserDetailsService = StringUtils.hasLength(beanName)
|
||||
? this.beans.getBean(beanName, ReactiveUserDetailsService.class)
|
||||
@ -110,6 +112,7 @@ final class WithUserDetailsSecurityContextFactory implements WithSecurityContext
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullAway") // Dataflow analysis limitation
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return this.userDetailsService.findByUsername(username).block();
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Security support classes for the Spring TestContext Framework.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.context.support;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -29,6 +29,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@ -190,6 +191,7 @@ public final class SecurityMockServerConfigurers {
|
||||
* @return the {@link OAuth2LoginMutator} to further configure or use
|
||||
* @since 5.3
|
||||
*/
|
||||
@NullUnmarked
|
||||
public static OAuth2LoginMutator mockOAuth2Login() {
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null,
|
||||
null, Collections.singleton("read"));
|
||||
@ -203,6 +205,7 @@ public final class SecurityMockServerConfigurers {
|
||||
* @return the {@link OidcLoginMutator} to further configure or use
|
||||
* @since 5.3
|
||||
*/
|
||||
@NullUnmarked
|
||||
public static OidcLoginMutator mockOidcLogin() {
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null,
|
||||
null, Collections.singleton("read"));
|
||||
@ -252,6 +255,7 @@ public final class SecurityMockServerConfigurers {
|
||||
private CsrfMutator() {
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void afterConfigurerAdded(WebTestClient.Builder builder,
|
||||
@Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) {
|
||||
@ -394,6 +398,7 @@ public final class SecurityMockServerConfigurers {
|
||||
builder.filters(addSetupMutatorFilter());
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void afterConfigurerAdded(WebTestClient.Builder builder,
|
||||
@Nullable WebHttpHandlerBuilder webHttpHandlerBuilder,
|
||||
@ -537,6 +542,7 @@ public final class SecurityMockServerConfigurers {
|
||||
configurer().afterConfigureAdded(serverSpec);
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void afterConfigurerAdded(WebTestClient.Builder builder,
|
||||
@Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) {
|
||||
@ -547,6 +553,7 @@ public final class SecurityMockServerConfigurers {
|
||||
configurer().afterConfigurerAdded(builder, httpHandlerBuilder, connector);
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
private <T extends WebTestClientConfigurer & MockServerConfigurer> T configurer() {
|
||||
return mockAuthentication(
|
||||
new JwtAuthenticationToken(this.jwt, this.authoritiesConverter.convert(this.jwt)));
|
||||
@ -631,6 +638,7 @@ public final class SecurityMockServerConfigurers {
|
||||
configurer().afterConfigureAdded(serverSpec);
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void afterConfigurerAdded(WebTestClient.Builder builder,
|
||||
@Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) {
|
||||
@ -688,6 +696,7 @@ public final class SecurityMockServerConfigurers {
|
||||
return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", issuedAt, expiresAt);
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
private Instant getInstant(Map<String, Object> attributes, String name) {
|
||||
Object value = attributes.get(name);
|
||||
if (value == null) {
|
||||
@ -865,12 +874,15 @@ public final class SecurityMockServerConfigurers {
|
||||
|
||||
private OAuth2AccessToken accessToken;
|
||||
|
||||
@Nullable
|
||||
private OidcIdToken idToken;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private OidcUserInfo userInfo;
|
||||
|
||||
private Supplier<OidcUser> oidcUser = this::defaultPrincipal;
|
||||
|
||||
@Nullable
|
||||
private Collection<GrantedAuthority> authorities;
|
||||
|
||||
private OidcLoginMutator(OAuth2AccessToken accessToken) {
|
||||
@ -1015,6 +1027,7 @@ public final class SecurityMockServerConfigurers {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
private OidcIdToken getOidcIdToken() {
|
||||
if (this.idToken != null) {
|
||||
return this.idToken;
|
||||
@ -1036,10 +1049,12 @@ public final class SecurityMockServerConfigurers {
|
||||
* @author Josh Cummings
|
||||
* @since 5.3
|
||||
*/
|
||||
@NullUnmarked
|
||||
public static final class OAuth2ClientMutator implements WebTestClientConfigurer, MockServerConfigurer {
|
||||
|
||||
private String registrationId = "test";
|
||||
|
||||
@Nullable
|
||||
private ClientRegistration clientRegistration;
|
||||
|
||||
private String principalName = "user";
|
||||
@ -1115,12 +1130,14 @@ public final class SecurityMockServerConfigurers {
|
||||
public void afterConfigureAdded(WebTestClient.MockServerSpec<?> serverSpec) {
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void afterConfigurerAdded(WebTestClient.Builder builder,
|
||||
@Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) {
|
||||
httpHandlerBuilder.filters(addAuthorizedClientFilter());
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
private Consumer<List<WebFilter>> addAuthorizedClientFilter() {
|
||||
OAuth2AuthorizedClient client = getClient();
|
||||
return (filters) -> filters.add(0, (exchange, chain) -> {
|
||||
@ -1136,6 +1153,7 @@ public final class SecurityMockServerConfigurers {
|
||||
});
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
private OAuth2AuthorizedClient getClient() {
|
||||
Assert.notNull(this.clientRegistration,
|
||||
"Please specify a ClientRegistration via one of the clientRegistration methods");
|
||||
@ -1163,12 +1181,14 @@ public final class SecurityMockServerConfigurers {
|
||||
|
||||
private final ReactiveOAuth2AuthorizedClientManager delegate;
|
||||
|
||||
@Nullable
|
||||
private ServerOAuth2AuthorizedClientRepository authorizedClientRepository;
|
||||
|
||||
TestOAuth2AuthorizedClientManager(ReactiveOAuth2AuthorizedClientManager delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public Mono<OAuth2AuthorizedClient> authorize(OAuth2AuthorizeRequest authorizeRequest) {
|
||||
ServerWebExchange exchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName());
|
||||
@ -1183,7 +1203,8 @@ public final class SecurityMockServerConfigurers {
|
||||
exchange.getAttributes().put(ENABLED_ATTR_NAME, Boolean.TRUE);
|
||||
}
|
||||
|
||||
boolean isEnabled(ServerWebExchange exchange) {
|
||||
@NullUnmarked
|
||||
boolean isEnabled(@Nullable ServerWebExchange exchange) {
|
||||
return Boolean.TRUE.equals(exchange.getAttribute(ENABLED_ATTR_NAME));
|
||||
}
|
||||
|
||||
@ -1202,7 +1223,8 @@ public final class SecurityMockServerConfigurers {
|
||||
|
||||
private final ServerOAuth2AuthorizedClientRepository delegate;
|
||||
|
||||
TestOAuth2AuthorizedClientRepository(ServerOAuth2AuthorizedClientRepository delegate) {
|
||||
@NullUnmarked
|
||||
TestOAuth2AuthorizedClientRepository(@Nullable ServerOAuth2AuthorizedClientRepository delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@ -1261,7 +1283,8 @@ public final class SecurityMockServerConfigurers {
|
||||
* @return the {@link ReactiveOAuth2AuthorizedClientManager} for the specified
|
||||
* {@link ServerWebExchange}
|
||||
*/
|
||||
static ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository(ServerWebExchange exchange) {
|
||||
static @Nullable ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository(
|
||||
ServerWebExchange exchange) {
|
||||
ReactiveOAuth2AuthorizedClientManager manager = getOAuth2AuthorizedClientManager(exchange);
|
||||
if (manager == null) {
|
||||
return DEFAULT_CLIENT_REPO;
|
||||
@ -1294,7 +1317,8 @@ public final class SecurityMockServerConfigurers {
|
||||
((TestOAuth2AuthorizedClientManager) manager).authorizedClientRepository = repository;
|
||||
}
|
||||
|
||||
static ReactiveOAuth2AuthorizedClientManager getOAuth2AuthorizedClientManager(ServerWebExchange exchange) {
|
||||
static @Nullable ReactiveOAuth2AuthorizedClientManager getOAuth2AuthorizedClientManager(
|
||||
ServerWebExchange exchange) {
|
||||
OAuth2AuthorizedClientArgumentResolver resolver = findResolver(exchange,
|
||||
OAuth2AuthorizedClientArgumentResolver.class);
|
||||
if (resolver == null) {
|
||||
@ -1323,7 +1347,7 @@ public final class SecurityMockServerConfigurers {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends HandlerMethodArgumentResolver> T findResolver(ServerWebExchange exchange,
|
||||
static <T extends HandlerMethodArgumentResolver> @Nullable T findResolver(ServerWebExchange exchange,
|
||||
Class<T> resolverClass) {
|
||||
if (!ClassUtils.isPresent(
|
||||
"org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter",
|
||||
@ -1335,7 +1359,7 @@ public final class SecurityMockServerConfigurers {
|
||||
|
||||
private static class WebFluxClasspathGuard {
|
||||
|
||||
static <T extends HandlerMethodArgumentResolver> T findResolver(ServerWebExchange exchange,
|
||||
static <T extends HandlerMethodArgumentResolver> @Nullable T findResolver(ServerWebExchange exchange,
|
||||
Class<T> resolverClass) {
|
||||
RequestMappingHandlerAdapter handlerAdapter = getRequestMappingHandlerAdapter(exchange);
|
||||
if (handlerAdapter == null) {
|
||||
@ -1358,7 +1382,7 @@ public final class SecurityMockServerConfigurers {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(
|
||||
private static @Nullable RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(
|
||||
ServerWebExchange exchange) {
|
||||
ApplicationContext context = exchange.getApplicationContext();
|
||||
if (context != null) {
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Security upport for testing Spring WebFlux server endpoints via WebTestClient.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.web.reactive.server;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -17,6 +17,7 @@
|
||||
package org.springframework.security.test.web.servlet.request;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.Mergeable;
|
||||
import org.springframework.http.MediaType;
|
||||
@ -91,7 +92,7 @@ public final class SecurityMockMvcRequestBuilders {
|
||||
|
||||
private RequestPostProcessor postProcessor = csrf();
|
||||
|
||||
private Mergeable parent;
|
||||
private @Nullable Mergeable parent;
|
||||
|
||||
private LogoutRequestBuilder() {
|
||||
}
|
||||
@ -135,7 +136,7 @@ public final class SecurityMockMvcRequestBuilders {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object merge(Object parent) {
|
||||
public Object merge(@Nullable Object parent) {
|
||||
if (parent == null) {
|
||||
return this;
|
||||
}
|
||||
@ -168,7 +169,7 @@ public final class SecurityMockMvcRequestBuilders {
|
||||
|
||||
private MediaType acceptMediaType = MediaType.APPLICATION_FORM_URLENCODED;
|
||||
|
||||
private Mergeable parent;
|
||||
private @Nullable Mergeable parent;
|
||||
|
||||
private RequestPostProcessor postProcessor = csrf();
|
||||
|
||||
@ -297,7 +298,7 @@ public final class SecurityMockMvcRequestBuilders {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object merge(Object parent) {
|
||||
public Object merge(@Nullable Object parent) {
|
||||
if (parent == null) {
|
||||
return this;
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ import java.util.stream.Collectors;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
@ -397,6 +399,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
* @return the {@link OidcLoginRequestPostProcessor} for additional customization
|
||||
* @since 5.3
|
||||
*/
|
||||
@NullUnmarked
|
||||
public static OAuth2LoginRequestPostProcessor oauth2Login() {
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null,
|
||||
null, Collections.singleton("read"));
|
||||
@ -425,6 +428,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
* @return the {@link OidcLoginRequestPostProcessor} for additional customization
|
||||
* @since 5.3
|
||||
*/
|
||||
@NullUnmarked
|
||||
public static OidcLoginRequestPostProcessor oidcLogin() {
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null,
|
||||
null, Collections.singleton("read"));
|
||||
@ -513,6 +517,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
private CsrfRequestPostProcessor() {
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
CsrfTokenRepository repository = WebTestUtils.getCsrfTokenRepository(request);
|
||||
@ -577,7 +582,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
|
||||
public void saveToken(@Nullable CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
|
||||
if (isEnabled(request)) {
|
||||
request.setAttribute(TOKEN_ATTR_NAME, token);
|
||||
}
|
||||
@ -587,7 +592,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CsrfToken loadToken(HttpServletRequest request) {
|
||||
public @Nullable CsrfToken loadToken(HttpServletRequest request) {
|
||||
if (isEnabled(request)) {
|
||||
return (CsrfToken) request.getAttribute(TOKEN_ATTR_NAME);
|
||||
}
|
||||
@ -697,8 +702,9 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
* @return the MD5 of the digest authentication response, encoded in hex
|
||||
* @throws IllegalArgumentException if the supplied qop value is unsupported.
|
||||
*/
|
||||
private static String generateDigest(String username, String realm, String password, String httpMethod,
|
||||
String uri, String qop, String nonce, String nc, String cnonce) throws IllegalArgumentException {
|
||||
private static String generateDigest(String username, String realm, String password,
|
||||
@Nullable String httpMethod, @Nullable String uri, String qop, String nonce, String nc, String cnonce)
|
||||
throws IllegalArgumentException {
|
||||
String a1Md5 = encodePasswordInA1Format(username, realm, password);
|
||||
String a2 = httpMethod + ":" + uri;
|
||||
String a2Md5 = md5Hex(a2);
|
||||
@ -1129,6 +1135,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
CsrfFilter.skipRequest(request);
|
||||
@ -1255,6 +1262,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", issuedAt, expiresAt);
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
private Instant getInstant(Map<String, Object> attributes, String name) {
|
||||
Object value = attributes.get(name);
|
||||
if (value == null) {
|
||||
@ -1407,13 +1415,14 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
|
||||
private OAuth2AccessToken accessToken;
|
||||
|
||||
private OidcIdToken idToken;
|
||||
private @Nullable OidcIdToken idToken;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private OidcUserInfo userInfo;
|
||||
|
||||
private Supplier<OidcUser> oidcUser = this::defaultPrincipal;
|
||||
|
||||
private Collection<GrantedAuthority> authorities;
|
||||
private @Nullable Collection<GrantedAuthority> authorities;
|
||||
|
||||
private OidcLoginRequestPostProcessor(OAuth2AccessToken accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
@ -1525,6 +1534,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
private OidcIdToken getOidcIdToken() {
|
||||
if (this.idToken != null) {
|
||||
return this.idToken;
|
||||
@ -1546,11 +1556,12 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
* @author Josh Cummings
|
||||
* @since 5.3
|
||||
*/
|
||||
@NullUnmarked
|
||||
public static final class OAuth2ClientRequestPostProcessor implements RequestPostProcessor {
|
||||
|
||||
private String registrationId = "test";
|
||||
|
||||
private ClientRegistration clientRegistration;
|
||||
private @Nullable ClientRegistration clientRegistration;
|
||||
|
||||
private String principalName = "user";
|
||||
|
||||
@ -1610,6 +1621,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
if (this.clientRegistration == null) {
|
||||
@ -1650,14 +1662,15 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
|
||||
private final OAuth2AuthorizedClientManager delegate;
|
||||
|
||||
private OAuth2AuthorizedClientRepository authorizedClientRepository;
|
||||
private @Nullable OAuth2AuthorizedClientRepository authorizedClientRepository;
|
||||
|
||||
TestOAuth2AuthorizedClientManager(OAuth2AuthorizedClientManager delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public OAuth2AuthorizedClient authorize(OAuth2AuthorizeRequest authorizeRequest) {
|
||||
public @Nullable OAuth2AuthorizedClient authorize(OAuth2AuthorizeRequest authorizeRequest) {
|
||||
HttpServletRequest request = authorizeRequest.getAttribute(HttpServletRequest.class.getName());
|
||||
if (isEnabled(request)) {
|
||||
return this.authorizedClientRepository.loadAuthorizedClient(
|
||||
@ -1670,7 +1683,8 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
request.setAttribute(ENABLED_ATTR_NAME, Boolean.TRUE);
|
||||
}
|
||||
|
||||
boolean isEnabled(HttpServletRequest request) {
|
||||
@NullUnmarked
|
||||
boolean isEnabled(@Nullable HttpServletRequest request) {
|
||||
return Boolean.TRUE.equals(request.getAttribute(ENABLED_ATTR_NAME));
|
||||
}
|
||||
|
||||
@ -1689,7 +1703,8 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
|
||||
private final OAuth2AuthorizedClientRepository delegate;
|
||||
|
||||
TestOAuth2AuthorizedClientRepository(OAuth2AuthorizedClientRepository delegate) {
|
||||
@NullUnmarked
|
||||
TestOAuth2AuthorizedClientRepository(@Nullable OAuth2AuthorizedClientRepository delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@ -1748,7 +1763,8 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
* @return the {@link OAuth2AuthorizedClientManager} for the specified
|
||||
* {@link HttpServletRequest}
|
||||
*/
|
||||
static OAuth2AuthorizedClientRepository getAuthorizedClientRepository(HttpServletRequest request) {
|
||||
static @Nullable OAuth2AuthorizedClientRepository getAuthorizedClientRepository(
|
||||
HttpServletRequest request) {
|
||||
OAuth2AuthorizedClientManager manager = getOAuth2AuthorizedClientManager(request);
|
||||
if (manager == null) {
|
||||
return DEFAULT_CLIENT_REPO;
|
||||
@ -1781,7 +1797,8 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
((TestOAuth2AuthorizedClientManager) manager).authorizedClientRepository = repository;
|
||||
}
|
||||
|
||||
static OAuth2AuthorizedClientManager getOAuth2AuthorizedClientManager(HttpServletRequest request) {
|
||||
static @Nullable OAuth2AuthorizedClientManager getOAuth2AuthorizedClientManager(
|
||||
HttpServletRequest request) {
|
||||
OAuth2AuthorizedClientArgumentResolver resolver = findResolver(request,
|
||||
OAuth2AuthorizedClientArgumentResolver.class);
|
||||
if (resolver == null) {
|
||||
@ -1809,7 +1826,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends HandlerMethodArgumentResolver> T findResolver(HttpServletRequest request,
|
||||
static <T extends HandlerMethodArgumentResolver> @Nullable T findResolver(HttpServletRequest request,
|
||||
Class<T> resolverClass) {
|
||||
if (!ClassUtils.isPresent(
|
||||
"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter", null)) {
|
||||
@ -1820,7 +1837,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
|
||||
private static class WebMvcClasspathGuard {
|
||||
|
||||
static <T extends HandlerMethodArgumentResolver> T findResolver(HttpServletRequest request,
|
||||
static <T extends HandlerMethodArgumentResolver> @Nullable T findResolver(HttpServletRequest request,
|
||||
Class<T> resolverClass) {
|
||||
ServletContext servletContext = request.getServletContext();
|
||||
RequestMappingHandlerAdapter mapping = getRequestMappingHandlerAdapter(servletContext);
|
||||
@ -1839,7 +1856,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(
|
||||
private static @Nullable RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(
|
||||
ServletContext servletContext) {
|
||||
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
|
||||
if (context != null) {
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Security built-in org.springframework.test.web.servlet.RequestBuilder
|
||||
* implementations.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.web.servlet.request;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -20,6 +20,9 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -81,21 +84,22 @@ public final class SecurityMockMvcResultMatchers {
|
||||
*/
|
||||
public static final class AuthenticatedMatcher extends AuthenticationMatcher<AuthenticatedMatcher> {
|
||||
|
||||
private SecurityContext expectedContext;
|
||||
private @Nullable SecurityContext expectedContext;
|
||||
|
||||
private Authentication expectedAuthentication;
|
||||
private @Nullable Authentication expectedAuthentication;
|
||||
|
||||
private Object expectedAuthenticationPrincipal;
|
||||
private @Nullable Object expectedAuthenticationPrincipal;
|
||||
|
||||
private String expectedAuthenticationName;
|
||||
private @Nullable String expectedAuthenticationName;
|
||||
|
||||
private Collection<? extends GrantedAuthority> expectedGrantedAuthorities;
|
||||
private @Nullable Collection<? extends GrantedAuthority> expectedGrantedAuthorities;
|
||||
|
||||
private Consumer<Authentication> assertAuthentication;
|
||||
private @Nullable Consumer<Authentication> assertAuthentication;
|
||||
|
||||
AuthenticatedMatcher() {
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public void match(MvcResult result) {
|
||||
SecurityContext context = load(result);
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Security server-side support for testing Spring MVC applications.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.web.servlet.response;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -24,6 +24,7 @@ import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
@ -66,6 +67,7 @@ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter {
|
||||
builder.addFilters(this.delegateFilter);
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
@Override
|
||||
public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> builder,
|
||||
WebApplicationContext context) {
|
||||
@ -100,6 +102,7 @@ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter {
|
||||
*/
|
||||
static class DelegateFilter implements Filter {
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private Filter delegate;
|
||||
|
||||
DelegateFilter() {
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Security built-in MockMvcBuilder implementations.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.web.servlet.setup;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@ -21,6 +21,8 @@ import java.util.List;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
@ -64,6 +66,7 @@ public abstract class WebTestUtils {
|
||||
* @return the {@link SecurityContextRepository} for the specified
|
||||
* {@link HttpServletRequest}
|
||||
*/
|
||||
@NullUnmarked
|
||||
public static SecurityContextRepository getSecurityContextRepository(HttpServletRequest request) {
|
||||
SecurityContextPersistenceFilter filter = findFilter(request, SecurityContextPersistenceFilter.class);
|
||||
if (filter != null) {
|
||||
@ -103,7 +106,7 @@ public abstract class WebTestUtils {
|
||||
* @return the {@link CsrfTokenRepository} for the specified
|
||||
* {@link HttpServletRequest}
|
||||
*/
|
||||
public static CsrfTokenRepository getCsrfTokenRepository(HttpServletRequest request) {
|
||||
public static @Nullable CsrfTokenRepository getCsrfTokenRepository(HttpServletRequest request) {
|
||||
CsrfFilter filter = findFilter(request, CsrfFilter.class);
|
||||
if (filter == null) {
|
||||
return DEFAULT_TOKEN_REPO;
|
||||
@ -120,7 +123,7 @@ public abstract class WebTestUtils {
|
||||
* @return the {@link CsrfTokenRequestHandler} for the specified
|
||||
* {@link HttpServletRequest}
|
||||
*/
|
||||
public static CsrfTokenRequestHandler getCsrfTokenRequestHandler(HttpServletRequest request) {
|
||||
public static @Nullable CsrfTokenRequestHandler getCsrfTokenRequestHandler(HttpServletRequest request) {
|
||||
CsrfFilter filter = findFilter(request, CsrfFilter.class);
|
||||
if (filter == null) {
|
||||
return DEFAULT_CSRF_HANDLER;
|
||||
@ -142,7 +145,7 @@ public abstract class WebTestUtils {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends Filter> T findFilter(HttpServletRequest request, Class<T> filterClass) {
|
||||
static <T extends Filter> @Nullable T findFilter(HttpServletRequest request, Class<T> filterClass) {
|
||||
ServletContext servletContext = request.getServletContext();
|
||||
Filter springSecurityFilterChain = getSpringSecurityFilterChain(servletContext);
|
||||
if (springSecurityFilterChain == null) {
|
||||
@ -160,7 +163,7 @@ public abstract class WebTestUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Filter getSpringSecurityFilterChain(ServletContext servletContext) {
|
||||
private static @Nullable Filter getSpringSecurityFilterChain(ServletContext servletContext) {
|
||||
Filter result = (Filter) servletContext.getAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
if (result != null) {
|
||||
return result;
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Security supporting the org.springframework.web.context package, such as
|
||||
* WebApplicationContext implementations and various utility classes.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.test.web.support;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
Loading…
x
Reference in New Issue
Block a user