Revert unnecessary merges on 6.0.x
This commit removes unnecessary main-branch merges starting from8750608b5band adds the following needed commit(s) that were made afterward: -5dce82c48b
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,8 +24,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -34,7 +32,6 @@ import org.springframework.util.Assert;
|
||||
* the framework.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Mark Chesney
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultRedirectStrategy implements RedirectStrategy {
|
||||
@@ -43,8 +40,6 @@ public class DefaultRedirectStrategy implements RedirectStrategy {
|
||||
|
||||
private boolean contextRelative;
|
||||
|
||||
private HttpStatus statusCode = HttpStatus.FOUND;
|
||||
|
||||
/**
|
||||
* Redirects the response to the supplied URL.
|
||||
* <p>
|
||||
@@ -60,14 +55,7 @@ public class DefaultRedirectStrategy implements RedirectStrategy {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(LogMessage.format("Redirecting to %s", redirectUrl));
|
||||
}
|
||||
if (this.statusCode == HttpStatus.FOUND) {
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
else {
|
||||
response.setHeader(HttpHeaders.LOCATION, redirectUrl);
|
||||
response.setStatus(this.statusCode.value());
|
||||
response.getWriter().flush();
|
||||
}
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
|
||||
protected String calculateRedirectUrl(String contextPath, String url) {
|
||||
@@ -108,18 +96,4 @@ public class DefaultRedirectStrategy implements RedirectStrategy {
|
||||
return this.contextRelative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HTTP status code to use. The default is {@link HttpStatus#FOUND}.
|
||||
* <p>
|
||||
* Note that according to RFC 7231, with {@link HttpStatus#FOUND}, a user agent MAY
|
||||
* change the request method from POST to GET for the subsequent request. If this
|
||||
* behavior is undesired, {@link HttpStatus#TEMPORARY_REDIRECT} can be used instead.
|
||||
* @param statusCode the HTTP status code to use.
|
||||
* @since 6.2
|
||||
*/
|
||||
public void setStatusCode(HttpStatus statusCode) {
|
||||
Assert.notNull(statusCode, "statusCode cannot be null");
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ public class FilterInvocation {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (!StringUtils.hasLength(this.request.getMethod())) {
|
||||
if (StringUtils.isEmpty(this.request.getMethod())) {
|
||||
return "filter invocation [" + getRequestUrl() + "]";
|
||||
}
|
||||
else {
|
||||
|
||||
+2
-55
@@ -18,9 +18,7 @@ package org.springframework.security.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -141,49 +139,6 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
|
||||
static final class ObservationFilter implements Filter {
|
||||
|
||||
static final Map<String, String> OBSERVATION_NAMES = new HashMap<>();
|
||||
|
||||
static {
|
||||
OBSERVATION_NAMES.put("DisableEncodeUrlFilter", "session.urlencoding");
|
||||
OBSERVATION_NAMES.put("ForceEagerSessionCreationFilter", "session.eagercreate");
|
||||
OBSERVATION_NAMES.put("ChannelProcessingFilter", "access.channel");
|
||||
OBSERVATION_NAMES.put("WebAsyncManagerIntegrationFilter", "context.async");
|
||||
OBSERVATION_NAMES.put("SecurityContextHolderFilter", "context.holder");
|
||||
OBSERVATION_NAMES.put("SecurityContextPersistenceFilter", "context.management");
|
||||
OBSERVATION_NAMES.put("HeaderWriterFilter", "header");
|
||||
OBSERVATION_NAMES.put("CorsFilter", "cors");
|
||||
OBSERVATION_NAMES.put("CsrfFilter", "csrf");
|
||||
OBSERVATION_NAMES.put("LogoutFilter", "logout");
|
||||
OBSERVATION_NAMES.put("OAuth2AuthorizationRequestRedirectFilter", "oauth2.authnrequest");
|
||||
OBSERVATION_NAMES.put("Saml2WebSsoAuthenticationRequestFilter", "saml2.authnrequest");
|
||||
OBSERVATION_NAMES.put("X509AuthenticationFilter", "authentication.x509");
|
||||
OBSERVATION_NAMES.put("J2eePreAuthenticatedProcessingFilter", "preauthentication.j2ee");
|
||||
OBSERVATION_NAMES.put("RequestHeaderAuthenticationFilter", "preauthentication.header");
|
||||
OBSERVATION_NAMES.put("RequestAttributeAuthenticationFilter", "preauthentication.attribute");
|
||||
OBSERVATION_NAMES.put("WebSpherePreAuthenticatedProcessingFilter", "preauthentication.websphere");
|
||||
OBSERVATION_NAMES.put("CasAuthenticationFilter", "cas.authentication");
|
||||
OBSERVATION_NAMES.put("OAuth2LoginAuthenticationFilter", "oauth2.authentication");
|
||||
OBSERVATION_NAMES.put("Saml2WebSsoAuthenticationFilter", "saml2.authentication");
|
||||
OBSERVATION_NAMES.put("UsernamePasswordAuthenticationFilter", "authentication.form");
|
||||
OBSERVATION_NAMES.put("DefaultLoginPageGeneratingFilter", "page.login");
|
||||
OBSERVATION_NAMES.put("DefaultLogoutPageGeneratingFilter", "page.logout");
|
||||
OBSERVATION_NAMES.put("ConcurrentSessionFilter", "session.concurrent");
|
||||
OBSERVATION_NAMES.put("DigestAuthenticationFilter", "authentication.digest");
|
||||
OBSERVATION_NAMES.put("BearerTokenAuthenticationFilter", "authentication.bearer");
|
||||
OBSERVATION_NAMES.put("BasicAuthenticationFilter", "authentication.basic");
|
||||
OBSERVATION_NAMES.put("RequestCacheAwareFilter", "requestcache");
|
||||
OBSERVATION_NAMES.put("SecurityContextHolderAwareRequestFilter", "context.servlet");
|
||||
OBSERVATION_NAMES.put("JaasApiIntegrationFilter", "jaas");
|
||||
OBSERVATION_NAMES.put("RememberMeAuthenticationFilter", "authentication.rememberme");
|
||||
OBSERVATION_NAMES.put("AnonymousAuthenticationFilter", "authentication.anonymous");
|
||||
OBSERVATION_NAMES.put("OAuth2AuthorizationCodeGrantFilter", "oauth2.client.code");
|
||||
OBSERVATION_NAMES.put("SessionManagementFilter", "session.management");
|
||||
OBSERVATION_NAMES.put("ExceptionTranslationFilter", "access.exceptions");
|
||||
OBSERVATION_NAMES.put("FilterSecurityInterceptor", "access.request");
|
||||
OBSERVATION_NAMES.put("AuthorizationFilter", "authorization");
|
||||
OBSERVATION_NAMES.put("SwitchUserFilter", "authentication.switch");
|
||||
}
|
||||
|
||||
private final ObservationRegistry registry;
|
||||
|
||||
private final FilterChainObservationConvention convention = new FilterChainObservationConvention();
|
||||
@@ -192,8 +147,6 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String eventName;
|
||||
|
||||
private final int position;
|
||||
|
||||
private final int size;
|
||||
@@ -204,12 +157,6 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
this.name = filter.getClass().getSimpleName();
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
this.eventName = eventName(this.name);
|
||||
}
|
||||
|
||||
private String eventName(String className) {
|
||||
String eventName = OBSERVATION_NAMES.get(className);
|
||||
return (eventName != null) ? eventName : className;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
@@ -236,7 +183,7 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
parentBefore.setFilterName(this.name);
|
||||
parentBefore.setChainPosition(this.position);
|
||||
}
|
||||
parent.before().event(Observation.Event.of(this.eventName + ".before", "before " + this.name));
|
||||
parent.before().event(Observation.Event.of(this.name + ".before", "before " + this.name));
|
||||
this.filter.doFilter(request, response, chain);
|
||||
parent.start();
|
||||
if (parent.after().getContext() instanceof FilterChainObservationContext parentAfter) {
|
||||
@@ -244,7 +191,7 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
parentAfter.setFilterName(this.name);
|
||||
parentAfter.setChainPosition(this.size - this.position + 1);
|
||||
}
|
||||
parent.after().event(Observation.Event.of(this.eventName + ".after", "after " + this.name));
|
||||
parent.after().event(Observation.Event.of(this.name + ".after", "after " + this.name));
|
||||
}
|
||||
|
||||
private AroundFilterObservation parent(HttpServletRequest request) {
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean implements Mes
|
||||
|
||||
private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
|
||||
|
||||
private final RequestCache requestCache;
|
||||
private RequestCache requestCache = new HttpSessionRequestCache();
|
||||
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.web.access;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
|
||||
/**
|
||||
* An {@link AccessDeniedHandler} implementation that does nothing.
|
||||
*
|
||||
* @author Marcus da Coregio
|
||||
* @since 6.2
|
||||
*/
|
||||
public class NoOpAccessDeniedHandler implements AccessDeniedHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
AccessDeniedException accessDeniedException) throws IOException, ServletException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+1
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -170,25 +170,7 @@ public class AuthorizationFilter extends GenericFilterBean {
|
||||
* @param shouldFilterAllDispatcherTypes should filter all dispatcher types. Default
|
||||
* is {@code true}
|
||||
* @since 5.7
|
||||
* @deprecated Permit access to the {@link jakarta.servlet.DispatcherType} instead.
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class SecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .authorizeHttpRequests((authorize) -> authorize
|
||||
* .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
|
||||
* // ...
|
||||
* );
|
||||
* return http.build();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Deprecated(since = "6.1", forRemoval = true)
|
||||
public void setShouldFilterAllDispatcherTypes(boolean shouldFilterAllDispatcherTypes) {
|
||||
this.observeOncePerRequest = !shouldFilterAllDispatcherTypes;
|
||||
this.filterErrorDispatch = shouldFilterAllDispatcherTypes;
|
||||
|
||||
@@ -48,9 +48,10 @@ public class RequestKey {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof RequestKey key)) {
|
||||
if (!(obj instanceof RequestKey)) {
|
||||
return false;
|
||||
}
|
||||
RequestKey key = (RequestKey) obj;
|
||||
if (!this.url.equals(key.url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-147
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -26,12 +26,9 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher.MatchResult;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||
@@ -105,8 +102,6 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
private boolean anyRequestConfigured;
|
||||
|
||||
private final List<RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>>> mappings = new ArrayList<>();
|
||||
|
||||
/**
|
||||
@@ -116,7 +111,6 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho
|
||||
* @return the {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder add(RequestMatcher matcher, AuthorizationManager<RequestAuthorizationContext> manager) {
|
||||
Assert.state(!this.anyRequestConfigured, "Can't add mappings after anyRequest");
|
||||
Assert.notNull(matcher, "matcher cannot be null");
|
||||
Assert.notNull(manager, "manager cannot be null");
|
||||
this.mappings.add(new RequestMatcherEntry<>(matcher, manager));
|
||||
@@ -133,34 +127,11 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho
|
||||
*/
|
||||
public Builder mappings(
|
||||
Consumer<List<RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>>>> mappingsConsumer) {
|
||||
Assert.state(!this.anyRequestConfigured, "Can't configure mappings after anyRequest");
|
||||
Assert.notNull(mappingsConsumer, "mappingsConsumer cannot be null");
|
||||
mappingsConsumer.accept(this.mappings);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps any request.
|
||||
* @return the {@link AuthorizedUrl} for further customizations
|
||||
* @since 6.2
|
||||
*/
|
||||
public AuthorizedUrl anyRequest() {
|
||||
Assert.state(!this.anyRequestConfigured, "Can't configure anyRequest after itself");
|
||||
this.anyRequestConfigured = true;
|
||||
return new AuthorizedUrl(AnyRequestMatcher.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps {@link RequestMatcher}s to {@link AuthorizationManager}.
|
||||
* @param matchers the {@link RequestMatcher}s to map
|
||||
* @return the {@link AuthorizedUrl} for further customizations
|
||||
* @since 6.2
|
||||
*/
|
||||
public AuthorizedUrl requestMatchers(RequestMatcher... matchers) {
|
||||
Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");
|
||||
return new AuthorizedUrl(matchers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RequestMatcherDelegatingAuthorizationManager} instance.
|
||||
* @return the {@link RequestMatcherDelegatingAuthorizationManager} instance
|
||||
@@ -169,123 +140,6 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho
|
||||
return new RequestMatcherDelegatingAuthorizationManager(this.mappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that allows configuring the {@link AuthorizationManager} for
|
||||
* {@link RequestMatcher}s.
|
||||
*
|
||||
* @author Evgeniy Cheban
|
||||
* @since 6.2
|
||||
*/
|
||||
public final class AuthorizedUrl {
|
||||
|
||||
private final List<RequestMatcher> matchers;
|
||||
|
||||
private AuthorizedUrl(RequestMatcher... matchers) {
|
||||
this(List.of(matchers));
|
||||
}
|
||||
|
||||
private AuthorizedUrl(List<RequestMatcher> matchers) {
|
||||
this.matchers = matchers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by anyone.
|
||||
* @return the {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder permitAll() {
|
||||
return access((a, o) -> new AuthorizationDecision(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are not allowed by anyone.
|
||||
* @return the {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder denyAll() {
|
||||
return access((a, o) -> new AuthorizationDecision(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by any authenticated user.
|
||||
* @return the {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder authenticated() {
|
||||
return access(AuthenticatedAuthorizationManager.authenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by users who have authenticated and were not
|
||||
* "remembered".
|
||||
* @return the {@link Builder} for further customization
|
||||
*/
|
||||
public Builder fullyAuthenticated() {
|
||||
return access(AuthenticatedAuthorizationManager.fullyAuthenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by users that have been remembered.
|
||||
* @return the {@link Builder} for further customization
|
||||
*/
|
||||
public Builder rememberMe() {
|
||||
return access(AuthenticatedAuthorizationManager.rememberMe());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by anonymous users.
|
||||
* @return the {@link Builder} for further customization
|
||||
*/
|
||||
public Builder anonymous() {
|
||||
return access(AuthenticatedAuthorizationManager.anonymous());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a user requires a role.
|
||||
* @param role the role that should be required which is prepended with ROLE_
|
||||
* automatically (i.e. USER, ADMIN, etc). It should not start with ROLE_
|
||||
* @return {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder hasRole(String role) {
|
||||
return access(AuthorityAuthorizationManager.hasRole(role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that a user requires one of many roles.
|
||||
* @param roles the roles that the user should have at least one of (i.e.
|
||||
* ADMIN, USER, etc). Each role should not start with ROLE_ since it is
|
||||
* automatically prepended already
|
||||
* @return the {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder hasAnyRole(String... roles) {
|
||||
return access(AuthorityAuthorizationManager.hasAnyRole(roles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a user requires an authority.
|
||||
* @param authority the authority that should be required
|
||||
* @return the {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder hasAuthority(String authority) {
|
||||
return access(AuthorityAuthorizationManager.hasAuthority(authority));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that a user requires one of many authorities.
|
||||
* @param authorities the authorities that the user should have at least one
|
||||
* of (i.e. ROLE_USER, ROLE_ADMIN, etc)
|
||||
* @return the {@link Builder} for further customizations
|
||||
*/
|
||||
public Builder hasAnyAuthority(String... authorities) {
|
||||
return access(AuthorityAuthorizationManager.hasAnyAuthority(authorities));
|
||||
}
|
||||
|
||||
private Builder access(AuthorizationManager<RequestAuthorizationContext> manager) {
|
||||
for (RequestMatcher matcher : this.matchers) {
|
||||
Builder.this.mappings.add(new RequestMatcherEntry<>(matcher, manager));
|
||||
}
|
||||
return Builder.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -107,36 +107,31 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
|
||||
if (isAlwaysUseDefaultTargetUrl()) {
|
||||
return this.defaultTargetUrl;
|
||||
}
|
||||
String targetUrlParameterValue = getTargetUrlParameterValue(request);
|
||||
if (StringUtils.hasText(targetUrlParameterValue)) {
|
||||
trace("Using url %s from request parameter %s", targetUrlParameterValue, this.targetUrlParameter);
|
||||
return targetUrlParameterValue;
|
||||
// Check for the parameter and use that if available
|
||||
String targetUrl = null;
|
||||
if (this.targetUrlParameter != null) {
|
||||
targetUrl = request.getParameter(this.targetUrlParameter);
|
||||
if (StringUtils.hasText(targetUrl)) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Using url %s from request parameter %s", targetUrl,
|
||||
this.targetUrlParameter));
|
||||
}
|
||||
return targetUrl;
|
||||
}
|
||||
}
|
||||
if (this.useReferer) {
|
||||
trace("Using url %s from Referer header", request.getHeader("Referer"));
|
||||
return request.getHeader("Referer");
|
||||
if (this.useReferer && !StringUtils.hasLength(targetUrl)) {
|
||||
targetUrl = request.getHeader("Referer");
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Using url %s from Referer header", targetUrl));
|
||||
}
|
||||
}
|
||||
return this.defaultTargetUrl;
|
||||
}
|
||||
|
||||
private String getTargetUrlParameterValue(HttpServletRequest request) {
|
||||
if (this.targetUrlParameter == null) {
|
||||
return null;
|
||||
}
|
||||
String value = request.getParameter(this.targetUrlParameter);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (StringUtils.hasText(value)) {
|
||||
return value;
|
||||
}
|
||||
return this.defaultTargetUrl;
|
||||
}
|
||||
|
||||
private void trace(String msg, String... msgParts) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format(msg, msgParts));
|
||||
if (!StringUtils.hasText(targetUrl)) {
|
||||
targetUrl = this.defaultTargetUrl;
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Using default url %s", targetUrl));
|
||||
}
|
||||
}
|
||||
return targetUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.web.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationEntryPoint} implementation that does nothing.
|
||||
*
|
||||
* @author Marcus da Coregio
|
||||
* @since 6.2
|
||||
*/
|
||||
public class NoOpAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -119,7 +119,7 @@ public abstract class AbstractRememberMeServices
|
||||
* which in turn is used to create a valid authentication token.
|
||||
*/
|
||||
@Override
|
||||
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
public final Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
String rememberMeCookie = extractRememberMeCookie(request);
|
||||
if (rememberMeCookie == null) {
|
||||
return null;
|
||||
@@ -253,7 +253,7 @@ public abstract class AbstractRememberMeServices
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginFail(HttpServletRequest request, HttpServletResponse response) {
|
||||
public final void loginFail(HttpServletRequest request, HttpServletResponse response) {
|
||||
this.logger.debug("Interactive login attempt was unsuccessful.");
|
||||
cancelCookie(request, response);
|
||||
onLoginFail(request, response);
|
||||
@@ -268,11 +268,11 @@ public abstract class AbstractRememberMeServices
|
||||
* <p>
|
||||
* Examines the incoming request and checks for the presence of the configured
|
||||
* "remember me" parameter. If it's present, or if <tt>alwaysRemember</tt> is set to
|
||||
* true, calls <tt>onLoginSuccess</tt>.
|
||||
* true, calls <tt>onLoginSucces</tt>.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
public final void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication) {
|
||||
if (!rememberMeRequested(request, this.parameter)) {
|
||||
this.logger.debug("Remember-me login not requested.");
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
|
||||
}
|
||||
Authentication rememberMeAuth = this.rememberMeServices.autoLogin(request, response);
|
||||
if (rememberMeAuth != null) {
|
||||
// Attempt authentication via AuthenticationManager
|
||||
// Attempt authenticaton via AuthenticationManager
|
||||
try {
|
||||
rememberMeAuth = this.authenticationManager.authenticate(rememberMeAuth);
|
||||
// Store to SecurityContextHolder
|
||||
|
||||
+1
-1
@@ -167,7 +167,7 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
|
||||
|
||||
private long getTokenExpiryTime(String[] cookieTokens) {
|
||||
try {
|
||||
return Long.valueOf(cookieTokens[1]);
|
||||
return new Long(cookieTokens[1]);
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new InvalidCookieException(
|
||||
|
||||
+3
-2
@@ -64,8 +64,9 @@ public final class SwitchUserGrantedAuthority implements GrantedAuthority {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof SwitchUserGrantedAuthority swa) {
|
||||
return this.role.equals(swa.getAuthority()) && this.source.equals(swa.getSource());
|
||||
if (obj instanceof SwitchUserGrantedAuthority) {
|
||||
SwitchUserGrantedAuthority swa = (SwitchUserGrantedAuthority) obj;
|
||||
return this.role.equals(swa.role) && this.source.equals(swa.source);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+15
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -96,8 +96,8 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
this.formLoginEnabled = true;
|
||||
this.usernameParameter = authFilter.getUsernameParameter();
|
||||
this.passwordParameter = authFilter.getPasswordParameter();
|
||||
if (authFilter.getRememberMeServices() instanceof AbstractRememberMeServices rememberMeServices) {
|
||||
this.rememberMeParameter = rememberMeServices.getParameter();
|
||||
if (authFilter.getRememberMeServices() instanceof AbstractRememberMeServices) {
|
||||
this.rememberMeParameter = ((AbstractRememberMeServices) authFilter.getRememberMeServices()).getParameter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,15 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
}
|
||||
|
||||
private String generateLoginPageHtml(HttpServletRequest request, boolean loginError, boolean logoutSuccess) {
|
||||
String errorMsg = loginError ? getLoginErrorMessage(request) : "Invalid credentials";
|
||||
String errorMsg = "Invalid credentials";
|
||||
if (loginError) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
AuthenticationException ex = (AuthenticationException) session
|
||||
.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
errorMsg = (ex != null) ? ex.getMessage() : "Invalid credentials";
|
||||
}
|
||||
}
|
||||
String contextPath = request.getContextPath();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<!DOCTYPE html>\n");
|
||||
@@ -203,7 +211,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
sb.append(" <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" "
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n");
|
||||
sb.append(" <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" "
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-oOE/3m0LUMPub4kaC09mrdEhIc+e3exm4xOGxAmuFXhBNF4hcg/6MiAXAf5p0P56\" crossorigin=\"anonymous\"/>\n");
|
||||
+ "rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n");
|
||||
sb.append(" </head>\n");
|
||||
sb.append(" <body>\n");
|
||||
sb.append(" <div class=\"container\">\n");
|
||||
@@ -264,15 +272,6 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getLoginErrorMessage(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null && session
|
||||
.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) instanceof AuthenticationException exception) {
|
||||
return exception.getMessage();
|
||||
}
|
||||
return "Invalid credentials";
|
||||
}
|
||||
|
||||
private String renderHiddenInputs(HttpServletRequest request) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, String> input : this.resolveHiddenInputs.apply(request).entrySet()) {
|
||||
@@ -304,14 +303,14 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
return matches(request, this.failureUrl);
|
||||
}
|
||||
|
||||
private String createError(boolean isError, String message) {
|
||||
private static String createError(boolean isError, String message) {
|
||||
if (!isError) {
|
||||
return "";
|
||||
}
|
||||
return "<div class=\"alert alert-danger\" role=\"alert\">" + HtmlUtils.htmlEscape(message) + "</div>";
|
||||
}
|
||||
|
||||
private String createLogoutSuccess(boolean isLogoutSuccess) {
|
||||
private static String createLogoutSuccess(boolean isLogoutSuccess) {
|
||||
if (!isLogoutSuccess) {
|
||||
return "";
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -73,7 +73,7 @@ public class DefaultLogoutPageGeneratingFilter extends OncePerRequestFilter {
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" "
|
||||
+ "crossorigin=\"anonymous\">\n");
|
||||
sb.append(" <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" "
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-oOE/3m0LUMPub4kaC09mrdEhIc+e3exm4xOGxAmuFXhBNF4hcg/6MiAXAf5p0P56\" crossorigin=\"anonymous\"/>\n");
|
||||
+ "rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n");
|
||||
sb.append(" </head>\n");
|
||||
sb.append(" <body>\n");
|
||||
sb.append(" <div class=\"container\">\n");
|
||||
|
||||
+5
-38
@@ -28,16 +28,15 @@ import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.NullRememberMeServices;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -106,7 +105,7 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private String credentialsCharset = "UTF-8";
|
||||
|
||||
private AuthenticationConverter authenticationConverter = new BasicAuthenticationConverter();
|
||||
private BasicAuthenticationConverter authenticationConverter = new BasicAuthenticationConverter();
|
||||
|
||||
private SecurityContextRepository securityContextRepository = new RequestAttributeSecurityContextRepository();
|
||||
|
||||
@@ -150,18 +149,6 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
this.securityContextRepository = securityContextRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the
|
||||
* {@link org.springframework.security.web.authentication.AuthenticationConverter} to
|
||||
* use. Defaults to {@link BasicAuthenticationConverter}
|
||||
* @param authenticationConverter the converter to use
|
||||
* @since 6.2
|
||||
*/
|
||||
public void setAuthenticationConverter(AuthenticationConverter authenticationConverter) {
|
||||
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
|
||||
this.authenticationConverter = authenticationConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(this.authenticationManager, "An AuthenticationManager is required");
|
||||
@@ -174,7 +161,7 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
try {
|
||||
Authentication authRequest = this.authenticationConverter.convert(request);
|
||||
UsernamePasswordAuthenticationToken authRequest = this.authenticationConverter.convert(request);
|
||||
if (authRequest == null) {
|
||||
this.logger.trace("Did not process authentication request since failed to find "
|
||||
+ "username and password in Basic Authorization header");
|
||||
@@ -263,19 +250,9 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
this.securityContextHolderStrategy = securityContextHolderStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationDetailsSource} to use. By default, it is set to use
|
||||
* the {@link WebAuthenticationDetailsSource}. Note that this configuration applies
|
||||
* exclusively when the {@link #authenticationConverter} is set to
|
||||
* {@link BasicAuthenticationConverter}. If you are utilizing a different
|
||||
* implementation, you will need to manually specify the authentication details on it.
|
||||
* @param authenticationDetailsSource the {@link AuthenticationDetailsSource} to use.
|
||||
*/
|
||||
public void setAuthenticationDetailsSource(
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
|
||||
if (this.authenticationConverter instanceof BasicAuthenticationConverter basicAuthenticationConverter) {
|
||||
basicAuthenticationConverter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
}
|
||||
this.authenticationConverter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
}
|
||||
|
||||
public void setRememberMeServices(RememberMeServices rememberMeServices) {
|
||||
@@ -283,20 +260,10 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
this.rememberMeServices = rememberMeServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the charset to use when decoding credentials to {@link String}s. By default,
|
||||
* it is set to {@code UTF-8}. Note that this configuration applies exclusively when
|
||||
* the {@link #authenticationConverter} is set to
|
||||
* {@link BasicAuthenticationConverter}. If you are utilizing a different
|
||||
* implementation, you will need to manually specify the charset on it.
|
||||
* @param credentialsCharset the charset to use.
|
||||
*/
|
||||
public void setCredentialsCharset(String credentialsCharset) {
|
||||
Assert.hasText(credentialsCharset, "credentialsCharset cannot be null or empty");
|
||||
this.credentialsCharset = credentialsCharset;
|
||||
if (this.authenticationConverter instanceof BasicAuthenticationConverter basicAuthenticationConverter) {
|
||||
basicAuthenticationConverter.setCredentialsCharset(Charset.forName(credentialsCharset));
|
||||
}
|
||||
this.authenticationConverter.setCredentialsCharset(Charset.forName(credentialsCharset));
|
||||
}
|
||||
|
||||
protected String getCredentialsCharset(HttpServletRequest httpRequest) {
|
||||
|
||||
+1
-1
@@ -385,7 +385,7 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
|
||||
}
|
||||
// Extract expiry time from nonce
|
||||
try {
|
||||
this.nonceExpiryTime = Long.valueOf(nonceTokens[0]);
|
||||
this.nonceExpiryTime = new Long(nonceTokens[0]);
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new BadCredentialsException(DigestAuthenticationFilter.this.messages.getMessage(
|
||||
|
||||
+47
-41
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
@@ -17,14 +17,12 @@
|
||||
package org.springframework.security.web.csrf;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
@@ -36,7 +34,6 @@ import org.springframework.web.util.WebUtils;
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Steve Riesenberg
|
||||
* @author Alex Montoya
|
||||
* @since 4.1
|
||||
*/
|
||||
public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||
@@ -66,18 +63,7 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||
|
||||
private int cookieMaxAge = -1;
|
||||
|
||||
private Consumer<ResponseCookie.ResponseCookieBuilder> cookieCustomizer = (builder) -> {
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a {@link Consumer} for a {@code ResponseCookieBuilder} that will be invoked for
|
||||
* each cookie being built, just before the call to {@code build()}.
|
||||
* @param cookieCustomizer consumer for a cookie builder
|
||||
* @since 6.1
|
||||
*/
|
||||
public void setCookieCustomizer(Consumer<ResponseCookie.ResponseCookieBuilder> cookieCustomizer) {
|
||||
Assert.notNull(cookieCustomizer, "cookieCustomizer must not be null");
|
||||
this.cookieCustomizer = cookieCustomizer;
|
||||
public CookieCsrfTokenRepository() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,17 +74,15 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||
@Override
|
||||
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
|
||||
String tokenValue = (token != null) ? token.getToken() : "";
|
||||
|
||||
ResponseCookie.ResponseCookieBuilder cookieBuilder = ResponseCookie.from(this.cookieName, tokenValue)
|
||||
.secure((this.secure != null) ? this.secure : request.isSecure())
|
||||
.path(StringUtils.hasLength(this.cookiePath) ? this.cookiePath : this.getRequestContext(request))
|
||||
.maxAge((token != null) ? this.cookieMaxAge : 0)
|
||||
.httpOnly(this.cookieHttpOnly)
|
||||
.domain(this.cookieDomain);
|
||||
|
||||
this.cookieCustomizer.accept(cookieBuilder);
|
||||
|
||||
response.addHeader(HttpHeaders.SET_COOKIE, cookieBuilder.build().toString());
|
||||
Cookie cookie = new Cookie(this.cookieName, tokenValue);
|
||||
cookie.setSecure((this.secure != null) ? this.secure : request.isSecure());
|
||||
cookie.setPath(StringUtils.hasLength(this.cookiePath) ? this.cookiePath : this.getRequestContext(request));
|
||||
cookie.setMaxAge((token != null) ? this.cookieMaxAge : 0);
|
||||
cookie.setHttpOnly(this.cookieHttpOnly);
|
||||
if (StringUtils.hasLength(this.cookieDomain)) {
|
||||
cookie.setDomain(this.cookieDomain);
|
||||
}
|
||||
response.addCookie(cookie);
|
||||
|
||||
// Set request attribute to signal that response has blank cookie value,
|
||||
// which allows loadToken to return null when token has been removed
|
||||
@@ -159,9 +143,11 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
* Sets the HttpOnly attribute on the cookie containing the CSRF token. Defaults to
|
||||
* <code>true</code>.
|
||||
* @param cookieHttpOnly <code>true</code> sets the HttpOnly attribute,
|
||||
* <code>false</code> does not set it
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setCookieHttpOnly(boolean cookieHttpOnly) {
|
||||
this.cookieHttpOnly = cookieHttpOnly;
|
||||
}
|
||||
@@ -172,14 +158,14 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to conveniently create an instance that creates cookies where
|
||||
* {@link Cookie#isHttpOnly()} is set to false.
|
||||
* @return an instance of CookieCsrfTokenRepository that creates cookies where
|
||||
* {@link Cookie#isHttpOnly()} is set to false.
|
||||
* Factory method to conveniently create an instance that has
|
||||
* {@link #setCookieHttpOnly(boolean)} set to false.
|
||||
* @return an instance of CookieCsrfTokenRepository with
|
||||
* {@link #setCookieHttpOnly(boolean)} set to false
|
||||
*/
|
||||
public static CookieCsrfTokenRepository withHttpOnlyFalse() {
|
||||
CookieCsrfTokenRepository result = new CookieCsrfTokenRepository();
|
||||
result.cookieHttpOnly = false;
|
||||
result.setCookieHttpOnly(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -205,28 +191,48 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the domain of the cookie that the expected CSRF token is saved to and read
|
||||
* from.
|
||||
* @param cookieDomain the domain of the cookie that the expected CSRF token is saved
|
||||
* to and read from
|
||||
* @since 5.2
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setCookieDomain(String cookieDomain) {
|
||||
this.cookieDomain = cookieDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets secure flag of the cookie that the expected CSRF token is saved to and read
|
||||
* from. By default secure flag depends on {@link ServletRequest#isSecure()}
|
||||
* @param secure the secure flag of the cookie that the expected CSRF token is saved
|
||||
* to and read from
|
||||
* @since 5.4
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setSecure(Boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximum age in seconds for the cookie that the expected CSRF token is saved to
|
||||
* and read from. By default maximum age value is -1.
|
||||
*
|
||||
* <p>
|
||||
* A positive value indicates that the cookie will expire after that many seconds have
|
||||
* passed. Note that the value is the <i>maximum</i> age when the cookie will expire,
|
||||
* not the cookie's current age.
|
||||
*
|
||||
* <p>
|
||||
* A negative value means that the cookie is not stored persistently and will be
|
||||
* deleted when the Web browser exits.
|
||||
*
|
||||
* <p>
|
||||
* A zero value causes the cookie to be deleted immediately therefore it is not a
|
||||
* valid value and in that case an {@link IllegalArgumentException} will be thrown.
|
||||
* @param cookieMaxAge an integer specifying the maximum age of the cookie in seconds;
|
||||
* if negative, means the cookie is not stored; if zero, the method throws an
|
||||
* {@link IllegalArgumentException}
|
||||
* @since 5.5
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setCookieMaxAge(int cookieMaxAge) {
|
||||
Assert.isTrue(cookieMaxAge != 0, "cookieMaxAge cannot be zero");
|
||||
this.cookieMaxAge = cookieMaxAge;
|
||||
|
||||
@@ -51,9 +51,9 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
*
|
||||
* <p>
|
||||
* Typically the {@link CsrfTokenRepository} implementation chooses to store the
|
||||
* {@link CsrfToken} in {@link HttpSession} with {@link HttpSessionCsrfTokenRepository}.
|
||||
* This is preferred to storing the token in a cookie which can be modified by a client
|
||||
* application.
|
||||
* {@link CsrfToken} in {@link HttpSession} with {@link HttpSessionCsrfTokenRepository}
|
||||
* wrapped by a {@link LazyCsrfTokenRepository}. This is preferred to storing the token in
|
||||
* a cookie which can be modified by a client application.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -72,7 +72,7 @@ public final class CsrfFilter extends OncePerRequestFilter {
|
||||
/**
|
||||
* The attribute name to use when marking a given request as one that should not be
|
||||
* filtered.
|
||||
* <p>
|
||||
*
|
||||
* To use, set the attribute on your {@link HttpServletRequest}: <pre>
|
||||
* CsrfFilter.skipRequest(request);
|
||||
* </pre>
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -97,7 +97,7 @@ public final class XorCsrfTokenRequestAttributeHandler extends CsrfTokenRequestA
|
||||
System.arraycopy(actualBytes, randomBytesSize, xoredCsrf, 0, tokenSize);
|
||||
|
||||
byte[] csrfBytes = xorCsrf(randomBytes, xoredCsrf);
|
||||
return (csrfBytes != null) ? Utf8.decode(csrfBytes) : null;
|
||||
return Utf8.decode(csrfBytes);
|
||||
}
|
||||
|
||||
private static String createXoredCsrfToken(SecureRandom secureRandom, String token) {
|
||||
@@ -114,9 +114,6 @@ public final class XorCsrfTokenRequestAttributeHandler extends CsrfTokenRequestA
|
||||
}
|
||||
|
||||
private static byte[] xorCsrf(byte[] randomBytes, byte[] csrfBytes) {
|
||||
if (csrfBytes.length < randomBytes.length) {
|
||||
return null;
|
||||
}
|
||||
int len = Math.min(randomBytes.length, csrfBytes.length);
|
||||
byte[] xoredCsrf = new byte[len];
|
||||
System.arraycopy(csrfBytes, 0, xoredCsrf, 0, csrfBytes.length);
|
||||
|
||||
+12
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -713,7 +713,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
}
|
||||
String value = super.getHeader(name);
|
||||
if (value != null) {
|
||||
validateAllowedHeaderValue(name, value);
|
||||
validateAllowedHeaderValue(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -734,7 +734,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
@Override
|
||||
public String nextElement() {
|
||||
String value = headers.nextElement();
|
||||
validateAllowedHeaderValue(name, value);
|
||||
validateAllowedHeaderValue(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -768,7 +768,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
}
|
||||
String value = super.getParameter(name);
|
||||
if (value != null) {
|
||||
validateAllowedParameterValue(name, value);
|
||||
validateAllowedParameterValue(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -781,7 +781,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
String[] values = entry.getValue();
|
||||
validateAllowedParameterName(name);
|
||||
for (String value : values) {
|
||||
validateAllowedParameterValue(name, value);
|
||||
validateAllowedParameterValue(value);
|
||||
}
|
||||
}
|
||||
return parameterMap;
|
||||
@@ -815,7 +815,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
String[] values = super.getParameterValues(name);
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
validateAllowedParameterValue(name, value);
|
||||
validateAllowedParameterValue(value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
@@ -828,10 +828,10 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateAllowedHeaderValue(String name, String value) {
|
||||
private void validateAllowedHeaderValue(String value) {
|
||||
if (!StrictHttpFirewall.this.allowedHeaderValues.test(value)) {
|
||||
throw new RequestRejectedException("The request was rejected because the header: \"" + name
|
||||
+ " \" has a value \"" + value + "\" that is not allowed.");
|
||||
throw new RequestRejectedException(
|
||||
"The request was rejected because the header value \"" + value + "\" is not allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,10 +842,10 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateAllowedParameterValue(String name, String value) {
|
||||
private void validateAllowedParameterValue(String value) {
|
||||
if (!StrictHttpFirewall.this.allowedParameterValues.test(value)) {
|
||||
throw new RequestRejectedException("The request was rejected because the parameter: \"" + name
|
||||
+ " \" has a value \"" + value + "\" that is not allowed.");
|
||||
throw new RequestRejectedException(
|
||||
"The request was rejected because the parameter value \"" + value + "\" is not allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -127,9 +127,10 @@ public class JaasApiIntegrationFilter extends GenericFilterBean {
|
||||
if (!authentication.isAuthenticated()) {
|
||||
return null;
|
||||
}
|
||||
if (!(authentication instanceof JaasAuthenticationToken token)) {
|
||||
if (!(authentication instanceof JaasAuthenticationToken)) {
|
||||
return null;
|
||||
}
|
||||
JaasAuthenticationToken token = (JaasAuthenticationToken) authentication;
|
||||
LoginContext loginContext = token.getLoginContext();
|
||||
if (loginContext == null) {
|
||||
return null;
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ public class CookieRequestCache implements RequestCache {
|
||||
|
||||
private static String getCookiePath(HttpServletRequest request) {
|
||||
String contextPath = request.getContextPath();
|
||||
return (StringUtils.hasLength(contextPath)) ? contextPath : "/";
|
||||
return (!StringUtils.isEmpty(contextPath)) ? contextPath : "/";
|
||||
}
|
||||
|
||||
private boolean matchesSavedRequest(HttpServletRequest request, SavedRequest savedRequest) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -31,28 +31,22 @@ public class SavedCookie implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
private final String name;
|
||||
private final java.lang.String name;
|
||||
|
||||
private final String value;
|
||||
private final java.lang.String value;
|
||||
|
||||
private final String comment;
|
||||
private final java.lang.String comment;
|
||||
|
||||
private final String domain;
|
||||
private final java.lang.String domain;
|
||||
|
||||
private final int maxAge;
|
||||
|
||||
private final String path;
|
||||
private final java.lang.String path;
|
||||
|
||||
private final boolean secure;
|
||||
|
||||
private final int version;
|
||||
|
||||
/**
|
||||
* @deprecated use
|
||||
* {@link org.springframework.security.web.savedrequest.SavedCookie#SavedCookie(String, String, String, int, String, boolean)}
|
||||
* instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "6.1")
|
||||
public SavedCookie(String name, String value, String comment, String domain, int maxAge, String path,
|
||||
boolean secure, int version) {
|
||||
this.name = name;
|
||||
@@ -65,13 +59,9 @@ public class SavedCookie implements Serializable {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public SavedCookie(String name, String value, String domain, int maxAge, String path, boolean secure) {
|
||||
this(name, value, null, domain, maxAge, path, secure, 0);
|
||||
}
|
||||
|
||||
public SavedCookie(Cookie cookie) {
|
||||
this(cookie.getName(), cookie.getValue(), cookie.getDomain(), cookie.getMaxAge(), cookie.getPath(),
|
||||
cookie.getSecure());
|
||||
this(cookie.getName(), cookie.getValue(), cookie.getComment(), cookie.getDomain(), cookie.getMaxAge(),
|
||||
cookie.getPath(), cookie.getSecure(), cookie.getVersion());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@@ -82,7 +72,6 @@ public class SavedCookie implements Serializable {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true, since = "6.1")
|
||||
public String getComment() {
|
||||
return this.comment;
|
||||
}
|
||||
@@ -103,7 +92,6 @@ public class SavedCookie implements Serializable {
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true, since = "6.1")
|
||||
public int getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
+16
-14
@@ -33,8 +33,6 @@ import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
/**
|
||||
* Provides request parameters, headers and cookies from either an original request or a
|
||||
* saved request.
|
||||
@@ -59,7 +57,10 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
protected static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
|
||||
|
||||
protected SavedRequest savedRequest;
|
||||
/** The default Locale if none are specified. */
|
||||
protected static Locale defaultLocale = Locale.getDefault();
|
||||
|
||||
protected SavedRequest savedRequest = null;
|
||||
|
||||
/**
|
||||
* The set of SimpleDateFormat formats to use in getDateHeader(). Notice that because
|
||||
@@ -100,12 +101,14 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaderNames() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Enumeration getHeaderNames() {
|
||||
return new Enumerator<>(this.savedRequest.getHeaderNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaders(String name) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Enumeration getHeaders(String name) {
|
||||
return new Enumerator<>(this.savedRequest.getHeaderValues(name));
|
||||
}
|
||||
|
||||
@@ -122,7 +125,8 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<Locale> getLocales() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Enumeration getLocales() {
|
||||
List<Locale> locales = this.savedRequest.getLocales();
|
||||
if (locales.isEmpty()) {
|
||||
// Fall back to default locale
|
||||
@@ -137,11 +141,6 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
|
||||
return this.savedRequest.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return getHeader(HttpHeaders.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the parameter is available from the wrapped request then the request has been
|
||||
* forwarded/included to a URL with parameters, either supplementing or overriding the
|
||||
@@ -166,7 +165,8 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map getParameterMap() {
|
||||
Set<String> names = getCombinedParameterNames();
|
||||
Map<String, String[]> parameterMap = new HashMap<>(names.size());
|
||||
for (String name : names) {
|
||||
@@ -175,6 +175,7 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
|
||||
return parameterMap;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Set<String> getCombinedParameterNames() {
|
||||
Set<String> names = new HashSet<>();
|
||||
names.addAll(super.getParameterMap().keySet());
|
||||
@@ -183,8 +184,9 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
return new Enumerator<>(getCombinedParameterNames());
|
||||
@SuppressWarnings("unchecked")
|
||||
public Enumeration getParameterNames() {
|
||||
return new Enumerator(getCombinedParameterNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ public class SimpleSavedRequest implements SavedRequest {
|
||||
}
|
||||
|
||||
public void setLocales(List<Locale> locales) {
|
||||
Assert.notNull(locales, "locales cannot be null");
|
||||
Assert.notNull("locales cannot be null");
|
||||
this.locales = locales;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class ServerFormLoginAuthenticationConverter implements Function<ServerWe
|
||||
@Override
|
||||
@Deprecated
|
||||
public Mono<Authentication> apply(ServerWebExchange exchange) {
|
||||
return exchange.getFormData().map(this::createAuthentication);
|
||||
return exchange.getFormData().map((data) -> createAuthentication(data));
|
||||
}
|
||||
|
||||
private UsernamePasswordAuthenticationToken createAuthentication(MultiValueMap<String, String> data) {
|
||||
|
||||
+2
-1
@@ -280,7 +280,8 @@ public class SwitchUserWebFilter implements WebFilter {
|
||||
private Optional<Authentication> extractSourceAuthentication(Authentication currentAuthentication) {
|
||||
// iterate over granted authorities and find the 'switch user' authority
|
||||
for (GrantedAuthority authority : currentAuthentication.getAuthorities()) {
|
||||
if (authority instanceof SwitchUserGrantedAuthority switchAuthority) {
|
||||
if (authority instanceof SwitchUserGrantedAuthority) {
|
||||
SwitchUserGrantedAuthority switchAuthority = (SwitchUserGrantedAuthority) authority;
|
||||
return Optional.of(switchAuthority.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
+34
-35
@@ -17,7 +17,6 @@
|
||||
package org.springframework.security.web.server.csrf;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
@@ -37,7 +36,6 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
* @author Eric Deandrea
|
||||
* @author Thomas Vitale
|
||||
* @author Alonso Araya
|
||||
* @author Alex Montoya
|
||||
* @since 5.1
|
||||
*/
|
||||
public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRepository {
|
||||
@@ -62,29 +60,15 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
|
||||
|
||||
private int cookieMaxAge = -1;
|
||||
|
||||
private Consumer<ResponseCookie.ResponseCookieBuilder> cookieCustomizer = (builder) -> {
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a {@link Consumer} for a {@code ResponseCookieBuilder} that will be invoked for
|
||||
* each cookie being built, just before the call to {@code build()}.
|
||||
* @param cookieCustomizer consumer for a cookie builder
|
||||
* @since 6.1
|
||||
*/
|
||||
public void setCookieCustomizer(Consumer<ResponseCookie.ResponseCookieBuilder> cookieCustomizer) {
|
||||
Assert.notNull(cookieCustomizer, "cookieCustomizer must not be null");
|
||||
this.cookieCustomizer = cookieCustomizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to conveniently create an instance that has creates cookies with
|
||||
* {@link ResponseCookie#isHttpOnly} set to false.
|
||||
* @return an instance of CookieCsrfTokenRepository that creates cookies with
|
||||
* {@link ResponseCookie#isHttpOnly} set to false
|
||||
* Factory method to conveniently create an instance that has
|
||||
* {@link #setCookieHttpOnly(boolean)} set to false.
|
||||
* @return an instance of CookieCsrfTokenRepository with
|
||||
* {@link #setCookieHttpOnly(boolean)} set to false
|
||||
*/
|
||||
public static CookieServerCsrfTokenRepository withHttpOnlyFalse() {
|
||||
CookieServerCsrfTokenRepository result = new CookieServerCsrfTokenRepository();
|
||||
result.setCookieCustomizer((cookie) -> cookie.httpOnly(false));
|
||||
result.setCookieHttpOnly(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -98,18 +82,16 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
|
||||
return Mono.fromRunnable(() -> {
|
||||
String tokenValue = (token != null) ? token.getToken() : "";
|
||||
// @formatter:off
|
||||
ResponseCookie.ResponseCookieBuilder cookieBuilder = ResponseCookie
|
||||
ResponseCookie cookie = ResponseCookie
|
||||
.from(this.cookieName, tokenValue)
|
||||
.domain(this.cookieDomain)
|
||||
.httpOnly(this.cookieHttpOnly)
|
||||
.maxAge(!tokenValue.isEmpty() ? this.cookieMaxAge : 0)
|
||||
.path((this.cookiePath != null) ? this.cookiePath : getRequestContext(exchange.getRequest()))
|
||||
.secure((this.secure != null) ? this.secure : (exchange.getRequest().getSslInfo() != null));
|
||||
|
||||
this.cookieCustomizer.accept(cookieBuilder);
|
||||
|
||||
.secure((this.secure != null) ? this.secure : (exchange.getRequest().getSslInfo() != null))
|
||||
.build();
|
||||
// @formatter:on
|
||||
exchange.getResponse().addCookie(cookieBuilder.build());
|
||||
exchange.getResponse().addCookie(cookie);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -125,9 +107,9 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
* Sets the HttpOnly attribute on the cookie containing the CSRF token
|
||||
* @param cookieHttpOnly True to mark the cookie as http only. False otherwise.
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setCookieHttpOnly(boolean cookieHttpOnly) {
|
||||
this.cookieHttpOnly = cookieHttpOnly;
|
||||
}
|
||||
@@ -168,27 +150,44 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
* Sets the cookie domain
|
||||
* @param cookieDomain The cookie domain
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setCookieDomain(String cookieDomain) {
|
||||
this.cookieDomain = cookieDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cookie secure flag. If not set, the value depends on
|
||||
* {@link ServerHttpRequest#getSslInfo()}.
|
||||
* @param secure The value for the secure flag
|
||||
* @since 5.5
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setSecure(boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximum age in seconds for the cookie that the expected CSRF token is saved to
|
||||
* and read from. By default maximum age value is -1.
|
||||
*
|
||||
* <p>
|
||||
* A positive value indicates that the cookie will expire after that many seconds have
|
||||
* passed. Note that the value is the <i>maximum</i> age when the cookie will expire,
|
||||
* not the cookie's current age.
|
||||
*
|
||||
* <p>
|
||||
* A negative value means that the cookie is not stored persistently and will be
|
||||
* deleted when the Web browser exits.
|
||||
*
|
||||
* <p>
|
||||
* A zero value causes the cookie to be deleted immediately therefore it is not a
|
||||
* valid value and in that case an {@link IllegalArgumentException} will be thrown.
|
||||
* @param cookieMaxAge an integer specifying the maximum age of the cookie in seconds;
|
||||
* if negative, means the cookie is not stored; if zero, the method throws an
|
||||
* {@link IllegalArgumentException}
|
||||
* @since 5.8
|
||||
* @deprecated Use {@link #setCookieCustomizer(Consumer)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public void setCookieMaxAge(int cookieMaxAge) {
|
||||
Assert.isTrue(cookieMaxAge != 0, "cookieMaxAge cannot be zero");
|
||||
this.cookieMaxAge = cookieMaxAge;
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -90,7 +90,7 @@ public final class XorServerCsrfTokenRequestAttributeHandler extends ServerCsrfT
|
||||
System.arraycopy(actualBytes, randomBytesSize, xoredCsrf, 0, tokenSize);
|
||||
|
||||
byte[] csrfBytes = xorCsrf(randomBytes, xoredCsrf);
|
||||
return (csrfBytes != null) ? Utf8.decode(csrfBytes) : null;
|
||||
return Utf8.decode(csrfBytes);
|
||||
}
|
||||
|
||||
private static String createXoredCsrfToken(SecureRandom secureRandom, String token) {
|
||||
@@ -107,9 +107,6 @@ public final class XorServerCsrfTokenRequestAttributeHandler extends ServerCsrfT
|
||||
}
|
||||
|
||||
private static byte[] xorCsrf(byte[] randomBytes, byte[] csrfBytes) {
|
||||
if (csrfBytes.length < randomBytes.length) {
|
||||
return null;
|
||||
}
|
||||
int len = Math.min(randomBytes.length, csrfBytes.length);
|
||||
byte[] xoredCsrf = new byte[len];
|
||||
System.arraycopy(csrfBytes, 0, xoredCsrf, 0, csrfBytes.length);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -101,7 +101,7 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" "
|
||||
+ "crossorigin=\"anonymous\">\n");
|
||||
page.append(" <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" "
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-oOE/3m0LUMPub4kaC09mrdEhIc+e3exm4xOGxAmuFXhBNF4hcg/6MiAXAf5p0P56\" crossorigin=\"anonymous\"/>\n");
|
||||
+ "rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n");
|
||||
page.append(" </head>\n");
|
||||
page.append(" <body>\n");
|
||||
page.append(" <div class=\"container\">\n");
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -81,7 +81,7 @@ public class LogoutPageGeneratingWebFilter implements WebFilter {
|
||||
page.append(" <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" "
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n");
|
||||
page.append(" <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" "
|
||||
+ "rel=\"stylesheet\" integrity=\"sha384-oOE/3m0LUMPub4kaC09mrdEhIc+e3exm4xOGxAmuFXhBNF4hcg/6MiAXAf5p0P56\" crossorigin=\"anonymous\"/>\n");
|
||||
+ "rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n");
|
||||
page.append(" </head>\n");
|
||||
page.append(" <body>\n");
|
||||
page.append(" <div class=\"container\">\n");
|
||||
|
||||
+2
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
|
||||
/**
|
||||
@@ -33,13 +32,12 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
* detected by the {@code SessionManagementFilter}.
|
||||
*
|
||||
* @author Craig Andrews
|
||||
* @author Mark Chesney
|
||||
*/
|
||||
public final class RequestedUrlRedirectInvalidSessionStrategy implements InvalidSessionStrategy {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
private boolean createNewSession = true;
|
||||
|
||||
@@ -70,14 +68,4 @@ public final class RequestedUrlRedirectInvalidSessionStrategy implements Invalid
|
||||
this.createNewSession = createNewSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the redirect strategy to use. The default is {@link DefaultRedirectStrategy}.
|
||||
* @param redirectStrategy the redirect strategy to use.
|
||||
* @since 6.2
|
||||
*/
|
||||
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
|
||||
Assert.notNull(redirectStrategy, "redirectStrategy cannot be null");
|
||||
this.redirectStrategy = redirectStrategy;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ThrowableAnalyzer {
|
||||
*
|
||||
* @see Throwable#getCause()
|
||||
*/
|
||||
public static final ThrowableCauseExtractor DEFAULT_EXTRACTOR = Throwable::getCause;
|
||||
public static final ThrowableCauseExtractor DEFAULT_EXTRACTOR = (throwable) -> throwable.getCause();
|
||||
|
||||
/**
|
||||
* Default extractor for {@link InvocationTargetException} instances.
|
||||
|
||||
+1
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -17,9 +17,7 @@
|
||||
package org.springframework.security.web.util.matcher;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -68,28 +66,6 @@ public final class AndRequestMatcher implements RequestMatcher {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link MatchResult} for this {@link HttpServletRequest}. In the case of a
|
||||
* match, request variables are a composition of the request variables in underlying
|
||||
* matchers. In the event that two matchers have the same key, the last key is the one
|
||||
* propagated.
|
||||
* @param request the HTTP request
|
||||
* @return a {@link MatchResult} based on the given HTTP request
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public MatchResult matcher(HttpServletRequest request) {
|
||||
Map<String, String> variables = new LinkedHashMap<>();
|
||||
for (RequestMatcher matcher : this.requestMatchers) {
|
||||
MatchResult result = matcher.matcher(request);
|
||||
if (!result.isMatch()) {
|
||||
return MatchResult.notMatch();
|
||||
}
|
||||
variables.putAll(result.getVariables());
|
||||
}
|
||||
return MatchResult.match(variables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "And " + this.requestMatchers;
|
||||
|
||||
+2
-1
@@ -226,9 +226,10 @@ public final class AntPathRequestMatcher implements RequestMatcher, RequestVaria
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof AntPathRequestMatcher other)) {
|
||||
if (!(obj instanceof AntPathRequestMatcher)) {
|
||||
return false;
|
||||
}
|
||||
AntPathRequestMatcher other = (AntPathRequestMatcher) obj;
|
||||
return this.pattern.equals(other.pattern) && this.httpMethod == other.httpMethod
|
||||
&& this.caseSensitive == other.caseSensitive;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,7 +66,7 @@ public class DispatcherTypeRequestMatcher implements RequestMatcher {
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
if (this.httpMethod != null && StringUtils.hasText(request.getMethod())
|
||||
&& this.httpMethod != HttpMethod.valueOf(request.getMethod())) {
|
||||
&& this.httpMethod != HttpMethod.resolve(request.getMethod())) {
|
||||
return false;
|
||||
}
|
||||
return this.dispatcherType == request.getDispatcherType();
|
||||
|
||||
+1
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -62,25 +62,6 @@ public final class OrRequestMatcher implements RequestMatcher {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link MatchResult} for this {@link HttpServletRequest}. In the case of a
|
||||
* match, request variables are any request variables from the first underlying
|
||||
* matcher.
|
||||
* @param request the HTTP request
|
||||
* @return a {@link MatchResult} based on the given HTTP request
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public MatchResult matcher(HttpServletRequest request) {
|
||||
for (RequestMatcher matcher : this.requestMatchers) {
|
||||
MatchResult result = matcher.matcher(request);
|
||||
if (result.isMatch()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return MatchResult.notMatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Or " + this.requestMatchers;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -116,7 +116,7 @@ public final class RegexRequestMatcher implements RequestMatcher {
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
if (this.httpMethod != null && request.getMethod() != null
|
||||
&& this.httpMethod != HttpMethod.valueOf(request.getMethod())) {
|
||||
&& this.httpMethod != HttpMethod.resolve(request.getMethod())) {
|
||||
return false;
|
||||
}
|
||||
String url = request.getServletPath();
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.web.util.matcher;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A factory class to create {@link RequestMatcher} instances.
|
||||
*
|
||||
* @author Christian Schuster
|
||||
* @since 6.1
|
||||
*/
|
||||
public final class RequestMatchers {
|
||||
|
||||
/**
|
||||
* Creates a {@link RequestMatcher} that matches if at least one of the given
|
||||
* {@link RequestMatcher}s matches, if <code>matchers</code> are empty then the
|
||||
* returned matcher never matches.
|
||||
* @param matchers the {@link RequestMatcher}s to use
|
||||
* @return the any-of composed {@link RequestMatcher}
|
||||
* @see OrRequestMatcher
|
||||
*/
|
||||
public static RequestMatcher anyOf(RequestMatcher... matchers) {
|
||||
return (matchers.length > 0) ? new OrRequestMatcher(List.of(matchers)) : (request) -> false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RequestMatcher} that matches if all the given
|
||||
* {@link RequestMatcher}s match, if <code>matchers</code> are empty then the returned
|
||||
* matcher always matches.
|
||||
* @param matchers the {@link RequestMatcher}s to use
|
||||
* @return the all-of composed {@link RequestMatcher}
|
||||
* @see AndRequestMatcher
|
||||
*/
|
||||
public static RequestMatcher allOf(RequestMatcher... matchers) {
|
||||
return (matchers.length > 0) ? new AndRequestMatcher(List.of(matchers)) : (request) -> true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RequestMatcher} that matches if the given {@link RequestMatcher}
|
||||
* does not match.
|
||||
* @param matcher the {@link RequestMatcher} to use
|
||||
* @return the inverted {@link RequestMatcher}
|
||||
*/
|
||||
public static RequestMatcher not(RequestMatcher matcher) {
|
||||
return (request) -> !matcher.matches(request);
|
||||
}
|
||||
|
||||
private RequestMatchers() {
|
||||
}
|
||||
|
||||
}
|
||||
+1
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.security.web;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
@@ -27,7 +26,6 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @author Mark Chesney
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultRedirectStrategyTests {
|
||||
@@ -66,21 +64,4 @@ public class DefaultRedirectStrategyTests {
|
||||
.isThrownBy(() -> rds.sendRedirect(request, response, "https://redirectme.somewhere.else"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeIsHandledCorrectly() throws Exception {
|
||||
// given
|
||||
DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
redirectStrategy.setStatusCode(HttpStatus.TEMPORARY_REDIRECT);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// when
|
||||
redirectStrategy.sendRedirect(request, response, "/requested");
|
||||
|
||||
// then
|
||||
assertThat(response.isCommitted()).isTrue();
|
||||
assertThat(response.getRedirectedUrl()).isEqualTo("/requested");
|
||||
assertThat(response.getStatus()).isEqualTo(307);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-25
@@ -97,24 +97,6 @@ public class ObservationFilterChainDecoratorTests {
|
||||
assertThat(events.get(1).getName()).isEqualTo(filter.getClass().getSimpleName() + ".after");
|
||||
}
|
||||
|
||||
@Test
|
||||
void decorateFiltersWhenDefaultsThenUsesEventName() throws Exception {
|
||||
ObservationHandler<?> handler = mock(ObservationHandler.class);
|
||||
given(handler.supportsContext(any())).willReturn(true);
|
||||
ObservationRegistry registry = ObservationRegistry.create();
|
||||
registry.observationConfig().observationHandler(handler);
|
||||
ObservationFilterChainDecorator decorator = new ObservationFilterChainDecorator(registry);
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
Filter filter = new BasicAuthenticationFilter();
|
||||
FilterChain decorated = decorator.decorate(chain, List.of(filter));
|
||||
decorated.doFilter(new MockHttpServletRequest("GET", "/"), new MockHttpServletResponse());
|
||||
ArgumentCaptor<Observation.Event> event = ArgumentCaptor.forClass(Observation.Event.class);
|
||||
verify(handler, times(2)).onEvent(event.capture(), any());
|
||||
List<Observation.Event> events = event.getAllValues();
|
||||
assertThat(events.get(0).getName()).isEqualTo("authentication.basic.before");
|
||||
assertThat(events.get(1).getName()).isEqualTo("authentication.basic.after");
|
||||
}
|
||||
|
||||
// gh-12787
|
||||
@Test
|
||||
void decorateFiltersWhenErrorsThenClosesObservationOnlyOnce() throws Exception {
|
||||
@@ -150,13 +132,6 @@ public class ObservationFilterChainDecoratorTests {
|
||||
.isEqualTo(expectedFilterNameTag);
|
||||
}
|
||||
|
||||
// gh-13660
|
||||
@Test
|
||||
void observationNamesDoNotContainDashes() {
|
||||
ObservationFilterChainDecorator.ObservationFilter.OBSERVATION_NAMES.values()
|
||||
.forEach((name) -> assertThat(name).doesNotContain("-"));
|
||||
}
|
||||
|
||||
static Stream<Arguments> decorateFiltersWhenCompletesThenHasSpringSecurityReachedFilterNameTag() {
|
||||
Filter filterWithName = new BasicAuthenticationFilter();
|
||||
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.web.access;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
class NoOpAccessDeniedHandlerTests {
|
||||
|
||||
private final NoOpAccessDeniedHandler handler = new NoOpAccessDeniedHandler();
|
||||
|
||||
@Test
|
||||
void handleWhenInvokedThenDoesNothing() throws Exception {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
AccessDeniedException exception = mock(AccessDeniedException.class);
|
||||
this.handler.handle(request, response, exception);
|
||||
verifyNoInteractions(request, response, exception);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-281
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -21,20 +21,16 @@ import java.util.function.Supplier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.authentication.TestAuthentication;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestMatcherDelegatingAuthorizationManager}.
|
||||
@@ -128,280 +124,4 @@ public class RequestMatcherDelegatingAuthorizationManagerTests {
|
||||
.withMessage("mappingsConsumer cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingsWhenConfiguredAfterAnyRequestThenException() {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.mappings((m) -> m.add(new RequestMatcherEntry<>(AnyRequestMatcher.INSTANCE,
|
||||
AuthenticatedAuthorizationManager.authenticated()))))
|
||||
.withMessage("Can't configure mappings after anyRequest");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addWhenConfiguredAfterAnyRequestThenException() {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.add(AnyRequestMatcher.INSTANCE, AuthenticatedAuthorizationManager.authenticated()))
|
||||
.withMessage("Can't add mappings after anyRequest");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMatchersWhenConfiguredAfterAnyRequestThenException() {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.requestMatchers(new AntPathRequestMatcher("/authenticated"))
|
||||
.authenticated()
|
||||
.build())
|
||||
.withMessage("Can't configure requestMatchers after anyRequest");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anyRequestWhenConfiguredAfterAnyRequestThenException() {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.build())
|
||||
.withMessage("Can't configure anyRequest after itself");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anyRequestWhenPermitAllThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.permitAll()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::anonymousUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anyRequestWhenDenyAllThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.denyAll()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedWhenAuthenticatedUserThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedWhenAnonymousUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::anonymousUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullyAuthenticatedWhenAuthenticatedUserThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.fullyAuthenticated()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullyAuthenticatedWhenAnonymousUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.fullyAuthenticated()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::anonymousUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullyAuthenticatedWhenRememberMeUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.fullyAuthenticated()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::rememberMeUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rememberMeWhenRememberMeUserThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.rememberMe()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::rememberMeUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rememberMeWhenAuthenticatedUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.rememberMe()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anonymousWhenAnonymousUserThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.anonymous()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::anonymousUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anonymousWhenAuthenticatedUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.anonymous()
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasRoleAdminWhenAuthenticatedUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasRole("ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasRoleAdminWhenAuthenticatedAdminThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasRole("ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAnyRoleUserOrAdminWhenAuthenticatedUserThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAnyRole("USER", "ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAnyRoleUserOrAdminWhenAuthenticatedAdminThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAnyRole("USER", "ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAnyRoleUserOrAdminWhenAnonymousUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAnyRole("USER", "ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::anonymousUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAuthorityRoleAdminWhenAuthenticatedUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAuthority("ROLE_ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAuthorityRoleAdminWhenAuthenticatedAdminThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAuthority("ROLE_ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAnyAuthorityRoleUserOrAdminWhenAuthenticatedUserThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAnyAuthorityRoleUserOrAdminWhenAuthenticatedAdminThenGrantedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAnyAuthorityRoleUserOrAdminWhenAnonymousUserThenDeniedDecision() {
|
||||
RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.anyRequest()
|
||||
.hasAnyRole("USER", "ADMIN")
|
||||
.build();
|
||||
AuthorizationDecision decision = manager.check(TestAuthentication::anonymousUser, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-111
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.web.authentication;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Dayan Kodippily
|
||||
*/
|
||||
public class AbstractAuthenticationTargetUrlRequestHandlerTests {
|
||||
|
||||
public static final String REQUEST_URI = "https://example.org";
|
||||
|
||||
public static final String DEFAULT_TARGET_URL = "/defaultTarget";
|
||||
|
||||
public static final String REFERER_URL = "https://www.springsource.com/";
|
||||
|
||||
public static final String TARGET_URL = "https://example.org/target";
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
private AbstractAuthenticationTargetUrlRequestHandler handler;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.handler = new AbstractAuthenticationTargetUrlRequestHandler() {
|
||||
@Override
|
||||
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
|
||||
return super.determineTargetUrl(request, response);
|
||||
}
|
||||
};
|
||||
this.handler.setDefaultTargetUrl(DEFAULT_TARGET_URL);
|
||||
this.request.setRequestURI(REQUEST_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnDefaultTargetUrlIfUseDefaultTargetUrlTrue() {
|
||||
this.handler.setAlwaysUseDefaultTargetUrl(true);
|
||||
assertThat(this.handler.determineTargetUrl(this.request, this.response)).isEqualTo(DEFAULT_TARGET_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnTargetUrlParamValueIfParamHasValue() {
|
||||
this.handler.setTargetUrlParameter("param");
|
||||
this.request.setParameter("param", TARGET_URL);
|
||||
assertThat(this.handler.determineTargetUrl(this.request, this.response)).isEqualTo(TARGET_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void targetUrlParamValueTakePrecedenceOverRefererIfParamHasValue() {
|
||||
this.handler.setUseReferer(true);
|
||||
this.handler.setTargetUrlParameter("param");
|
||||
this.request.setParameter("param", TARGET_URL);
|
||||
assertThat(this.handler.determineTargetUrl(this.request, this.response)).isEqualTo(TARGET_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnDefaultTargetUrlIfTargetUrlParamHasNoValue() {
|
||||
this.handler.setTargetUrlParameter("param");
|
||||
this.request.setParameter("param", "");
|
||||
assertThat(this.handler.determineTargetUrl(this.request, this.response)).isEqualTo(DEFAULT_TARGET_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnDefaultTargetUrlIfTargetUrlParamHasNoValueContainsOnlyWhiteSpaces() {
|
||||
this.handler.setTargetUrlParameter("param");
|
||||
this.request.setParameter("param", " ");
|
||||
assertThat(this.handler.determineTargetUrl(this.request, this.response)).isEqualTo(DEFAULT_TARGET_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnRefererUrlIfUseRefererIsTrue() {
|
||||
this.handler.setUseReferer(true);
|
||||
this.request.addHeader("Referer", REFERER_URL);
|
||||
assertThat(this.handler.determineTargetUrl(this.request, this.response)).isEqualTo(REFERER_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnDefaultTargetUrlIfUseRefererIsFalse() {
|
||||
this.handler.setUseReferer(false);
|
||||
this.request.addHeader("Referer", REFERER_URL);
|
||||
assertThat(this.handler.determineTargetUrl(this.request, this.response)).isEqualTo(DEFAULT_TARGET_URL);
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.web.authentication;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
class NoOpAuthenticationEntryPointTests {
|
||||
|
||||
private final NoOpAuthenticationEntryPoint authenticationEntryPoint = new NoOpAuthenticationEntryPoint();
|
||||
|
||||
@Test
|
||||
void commenceWhenInvokedThenDoesNothing() throws Exception {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
AuthenticationException exception = mock(AuthenticationException.class);
|
||||
this.authenticationEntryPoint.commence(request, response, exception);
|
||||
verifyNoInteractions(request, response, exception);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -42,7 +42,7 @@ public class PreAuthenticatedAuthenticationTokenTests {
|
||||
assertThat(token.getPrincipal()).isEqualTo(principal);
|
||||
assertThat(token.getCredentials()).isEqualTo(credentials);
|
||||
assertThat(token.getDetails()).isEqualTo(details);
|
||||
assertThat(token.getAuthorities()).isEmpty();
|
||||
assertThat(token.getAuthorities().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -53,7 +53,7 @@ public class PreAuthenticatedAuthenticationTokenTests {
|
||||
assertThat(token.getPrincipal()).isEqualTo(principal);
|
||||
assertThat(token.getCredentials()).isEqualTo(credentials);
|
||||
assertThat(token.getDetails()).isNull();
|
||||
assertThat(token.getAuthorities()).isEmpty();
|
||||
assertThat(token.getAuthorities().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+7
-7
@@ -95,10 +95,10 @@ public class JdbcTokenRepositoryImplTests {
|
||||
PersistentRememberMeToken token = new PersistentRememberMeToken("joeuser", "joesseries", "atoken", currentDate);
|
||||
this.repo.createNewToken(token);
|
||||
Map<String, Object> results = this.template.queryForMap("select * from persistent_logins");
|
||||
assertThat(results).containsEntry("last_used", currentDate);
|
||||
assertThat(results).containsEntry("username", "joeuser");
|
||||
assertThat(results).containsEntry("series", "joesseries");
|
||||
assertThat(results).containsEntry("token", "atoken");
|
||||
assertThat(results.get("last_used")).isEqualTo(currentDate);
|
||||
assertThat(results.get("username")).isEqualTo("joeuser");
|
||||
assertThat(results.get("series")).isEqualTo("joesseries");
|
||||
assertThat(results.get("token")).isEqualTo("atoken");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -157,9 +157,9 @@ public class JdbcTokenRepositoryImplTests {
|
||||
this.repo.updateToken("joesseries", "newtoken", new Date());
|
||||
Map<String, Object> results = this.template
|
||||
.queryForMap("select * from persistent_logins where series = 'joesseries'");
|
||||
assertThat(results).containsEntry("username", "joeuser");
|
||||
assertThat(results).containsEntry("series", "joesseries");
|
||||
assertThat(results).containsEntry("token", "newtoken");
|
||||
assertThat(results.get("username")).isEqualTo("joeuser");
|
||||
assertThat(results.get("series")).isEqualTo("joesseries");
|
||||
assertThat(results.get("token")).isEqualTo("newtoken");
|
||||
Date lastUsed = (Date) results.get("last_used");
|
||||
assertThat(lastUsed.getTime() > ts.getTime()).isTrue();
|
||||
}
|
||||
|
||||
+3
-3
@@ -93,7 +93,7 @@ public class PersistentTokenBasedRememberMeServicesTests {
|
||||
this.services.processAutoLoginCookie(new String[] { "series", "token" }, new MockHttpServletRequest(),
|
||||
response);
|
||||
assertThat(this.repo.getStoredToken().getSeries()).isEqualTo("series");
|
||||
assertThat(this.repo.getStoredToken().getTokenValue()).hasSize(16);
|
||||
assertThat(this.repo.getStoredToken().getTokenValue().length()).isEqualTo(16);
|
||||
String[] cookie = this.services.decodeCookie(response.getCookie("mycookiename").getValue());
|
||||
assertThat(cookie[0]).isEqualTo("series");
|
||||
assertThat(cookie[1]).isEqualTo(this.repo.getStoredToken().getTokenValue());
|
||||
@@ -108,8 +108,8 @@ public class PersistentTokenBasedRememberMeServicesTests {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
this.services.loginSuccess(new MockHttpServletRequest(), response,
|
||||
UsernamePasswordAuthenticationToken.unauthenticated("joe", "password"));
|
||||
assertThat(this.repo.getStoredToken().getSeries()).hasSize(16);
|
||||
assertThat(this.repo.getStoredToken().getTokenValue()).hasSize(16);
|
||||
assertThat(this.repo.getStoredToken().getSeries().length()).isEqualTo(16);
|
||||
assertThat(this.repo.getStoredToken().getTokenValue().length()).isEqualTo(16);
|
||||
String[] cookie = this.services.decodeCookie(response.getCookie("mycookiename").getValue());
|
||||
assertThat(cookie[0]).isEqualTo(this.repo.getStoredToken().getSeries());
|
||||
assertThat(cookie[1]).isEqualTo(this.repo.getStoredToken().getTokenValue());
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -45,7 +45,7 @@ public class DefaultLogoutPageGeneratingFilterTests {
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Confirm Log Out?</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" integrity=\"sha384-oOE/3m0LUMPub4kaC09mrdEhIc+e3exm4xOGxAmuFXhBNF4hcg/6MiAXAf5p0P56\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/logout\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Are you sure you want to log out?</h2>\n"
|
||||
|
||||
-57
@@ -21,7 +21,6 @@ import java.nio.charset.StandardCharsets;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -42,12 +41,9 @@ import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.test.web.CodecTestUtils;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -492,57 +488,4 @@ public class BasicAuthenticationFilterTests {
|
||||
assertThat(authenticationRequest.getName()).isEqualTo("rod");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenCustomAuthenticationConverterThatIgnoresRequestThenIgnores() throws Exception {
|
||||
this.filter.setAuthenticationConverter(new TestAuthenticationConverter());
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/ignored");
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
this.filter.doFilter(request, response, filterChain);
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
|
||||
verify(this.manager, never()).authenticate(any(Authentication.class));
|
||||
verify(filterChain).doFilter(any(ServletRequest.class), any(ServletResponse.class));
|
||||
verifyNoMoreInteractions(this.manager, filterChain);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenCustomAuthenticationConverterRequestThenAuthenticate() throws Exception {
|
||||
this.filter.setAuthenticationConverter(new TestAuthenticationConverter());
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/ok");
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
this.filter.doFilter(request, response, filterChain);
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull();
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("rod");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAuthenticationConverterWhenNullThenException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setAuthenticationConverter(null));
|
||||
}
|
||||
|
||||
static class TestAuthenticationConverter implements AuthenticationConverter {
|
||||
|
||||
private final RequestMatcher matcher = AntPathRequestMatcher.antMatcher("/ignored");
|
||||
|
||||
private final BasicAuthenticationConverter delegate = new BasicAuthenticationConverter();
|
||||
|
||||
@Override
|
||||
public Authentication convert(HttpServletRequest request) {
|
||||
if (this.matcher.matches(request)) {
|
||||
return null;
|
||||
}
|
||||
return this.delegate.convert(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-20
@@ -38,16 +38,16 @@ public class DigestAuthUtilsTests {
|
||||
String unsplit = "username=\"rod\", invalidEntryThatHasNoEqualsSign, realm=\"Contacts Realm\", nonce=\"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==\", uri=\"/spring-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4\", response=\"38644211cf9ac3da63ab639807e2baff\", qop=auth, nc=00000004, cnonce=\"2b8d329a8571b99a\"";
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(unsplit);
|
||||
Map<String, String> headerMap = DigestAuthUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
|
||||
assertThat(headerMap).containsEntry("username", "rod");
|
||||
assertThat(headerMap).containsEntry("realm", "Contacts Realm");
|
||||
assertThat(headerMap).containsEntry("nonce",
|
||||
"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==");
|
||||
assertThat(headerMap).containsEntry("uri",
|
||||
"/spring-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4");
|
||||
assertThat(headerMap).containsEntry("response", "38644211cf9ac3da63ab639807e2baff");
|
||||
assertThat(headerMap).containsEntry("qop", "auth");
|
||||
assertThat(headerMap).containsEntry("nc", "00000004");
|
||||
assertThat(headerMap).containsEntry("cnonce", "2b8d329a8571b99a");
|
||||
assertThat(headerMap.get("username")).isEqualTo("rod");
|
||||
assertThat(headerMap.get("realm")).isEqualTo("Contacts Realm");
|
||||
assertThat(headerMap.get("nonce"))
|
||||
.isEqualTo("MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==");
|
||||
assertThat(headerMap.get("uri"))
|
||||
.isEqualTo("/spring-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4");
|
||||
assertThat(headerMap.get("response")).isEqualTo("38644211cf9ac3da63ab639807e2baff");
|
||||
assertThat(headerMap.get("qop")).isEqualTo("auth");
|
||||
assertThat(headerMap.get("nc")).isEqualTo("00000004");
|
||||
assertThat(headerMap.get("cnonce")).isEqualTo("2b8d329a8571b99a");
|
||||
assertThat(headerMap).hasSize(8);
|
||||
}
|
||||
|
||||
@@ -56,16 +56,16 @@ public class DigestAuthUtilsTests {
|
||||
String unsplit = "username=\"rod\", realm=\"Contacts Realm\", nonce=\"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==\", uri=\"/spring-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4\", response=\"38644211cf9ac3da63ab639807e2baff\", qop=auth, nc=00000004, cnonce=\"2b8d329a8571b99a\"";
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(unsplit);
|
||||
Map<String, String> headerMap = DigestAuthUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", null);
|
||||
assertThat(headerMap).containsEntry("username", "\"rod\"");
|
||||
assertThat(headerMap).containsEntry("realm", "\"Contacts Realm\"");
|
||||
assertThat(headerMap).containsEntry("nonce",
|
||||
"\"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==\"");
|
||||
assertThat(headerMap).containsEntry("uri",
|
||||
"\"/spring-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4\"");
|
||||
assertThat(headerMap).containsEntry("response", "\"38644211cf9ac3da63ab639807e2baff\"");
|
||||
assertThat(headerMap).containsEntry("qop", "auth");
|
||||
assertThat(headerMap).containsEntry("nc", "00000004");
|
||||
assertThat(headerMap).containsEntry("cnonce", "\"2b8d329a8571b99a\"");
|
||||
assertThat(headerMap.get("username")).isEqualTo("\"rod\"");
|
||||
assertThat(headerMap.get("realm")).isEqualTo("\"Contacts Realm\"");
|
||||
assertThat(headerMap.get("nonce"))
|
||||
.isEqualTo("\"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==\"");
|
||||
assertThat(headerMap.get("uri"))
|
||||
.isEqualTo("\"/spring-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4\"");
|
||||
assertThat(headerMap.get("response")).isEqualTo("\"38644211cf9ac3da63ab639807e2baff\"");
|
||||
assertThat(headerMap.get("qop")).isEqualTo("auth");
|
||||
assertThat(headerMap.get("nc")).isEqualTo("00000004");
|
||||
assertThat(headerMap.get("cnonce")).isEqualTo("\"2b8d329a8571b99a\"");
|
||||
assertThat(headerMap).hasSize(8);
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -93,8 +93,8 @@ public class DigestAuthenticationEntryPointTests {
|
||||
String header = response.getHeader("WWW-Authenticate").toString().substring(7);
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header);
|
||||
Map<String, String> headerMap = DigestAuthUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
|
||||
assertThat(headerMap).containsEntry("realm", "hello");
|
||||
assertThat(headerMap).containsEntry("qop", "auth");
|
||||
assertThat(headerMap.get("realm")).isEqualTo("hello");
|
||||
assertThat(headerMap.get("qop")).isEqualTo("auth");
|
||||
assertThat(headerMap.get("stale")).isNull();
|
||||
checkNonceValid(headerMap.get("nonce"));
|
||||
}
|
||||
@@ -116,9 +116,9 @@ public class DigestAuthenticationEntryPointTests {
|
||||
String header = response.getHeader("WWW-Authenticate").toString().substring(7);
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header);
|
||||
Map<String, String> headerMap = DigestAuthUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
|
||||
assertThat(headerMap).containsEntry("realm", "hello");
|
||||
assertThat(headerMap).containsEntry("qop", "auth");
|
||||
assertThat(headerMap).containsEntry("stale", "true");
|
||||
assertThat(headerMap.get("realm")).isEqualTo("hello");
|
||||
assertThat(headerMap.get("qop")).isEqualTo("auth");
|
||||
assertThat(headerMap.get("stale")).isEqualTo("true");
|
||||
checkNonceValid(headerMap.get("nonce"));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ public class DigestAuthenticationFilterTests {
|
||||
String header = response.getHeader("WWW-Authenticate").toString().substring(7);
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header);
|
||||
Map<String, String> headerMap = DigestAuthUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
|
||||
assertThat(headerMap).containsEntry("stale", "true");
|
||||
assertThat(headerMap.get("stale")).isEqualTo("true");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+12
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.security.web.context;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
@@ -318,15 +319,14 @@ public class AbstractSecurityWebApplicationInitializerTests {
|
||||
ServletContext context = mock(ServletContext.class);
|
||||
FilterRegistration.Dynamic registration = mock(FilterRegistration.Dynamic.class);
|
||||
ArgumentCaptor<DelegatingFilterProxy> proxyCaptor = ArgumentCaptor.forClass(DelegatingFilterProxy.class);
|
||||
given(context.addFilter(eq("springSecurityFilterChain"), any(DelegatingFilterProxy.class)))
|
||||
.willReturn(registration);
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<Set<SessionTrackingMode>> modesCaptor = ArgumentCaptor.forClass(Set.class);
|
||||
given(context.addFilter(eq("springSecurityFilterChain"), proxyCaptor.capture())).willReturn(registration);
|
||||
ArgumentCaptor<Set<SessionTrackingMode>> modesCaptor = ArgumentCaptor
|
||||
.forClass(new HashSet<SessionTrackingMode>() {
|
||||
}.getClass());
|
||||
willDoNothing().given(context).setSessionTrackingModes(modesCaptor.capture());
|
||||
new AbstractSecurityWebApplicationInitializer() {
|
||||
}.onStartup(context);
|
||||
verify(context).addFilter(eq("springSecurityFilterChain"), proxyCaptor.capture());
|
||||
assertProxyDefaults(proxyCaptor.getValue());
|
||||
verify(context).setSessionTrackingModes(modesCaptor.capture());
|
||||
Set<SessionTrackingMode> modes = modesCaptor.getValue();
|
||||
assertThat(modes).hasSize(1);
|
||||
assertThat(modes).containsExactly(SessionTrackingMode.COOKIE);
|
||||
@@ -337,20 +337,18 @@ public class AbstractSecurityWebApplicationInitializerTests {
|
||||
ServletContext context = mock(ServletContext.class);
|
||||
FilterRegistration.Dynamic registration = mock(FilterRegistration.Dynamic.class);
|
||||
ArgumentCaptor<DelegatingFilterProxy> proxyCaptor = ArgumentCaptor.forClass(DelegatingFilterProxy.class);
|
||||
given(context.addFilter(eq("springSecurityFilterChain"), any(DelegatingFilterProxy.class)))
|
||||
.willReturn(registration);
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<Set<SessionTrackingMode>> modesCaptor = ArgumentCaptor.forClass(Set.class);
|
||||
willDoNothing().given(context).setSessionTrackingModes(any());
|
||||
given(context.addFilter(eq("springSecurityFilterChain"), proxyCaptor.capture())).willReturn(registration);
|
||||
ArgumentCaptor<Set<SessionTrackingMode>> modesCaptor = ArgumentCaptor
|
||||
.forClass(new HashSet<SessionTrackingMode>() {
|
||||
}.getClass());
|
||||
willDoNothing().given(context).setSessionTrackingModes(modesCaptor.capture());
|
||||
new AbstractSecurityWebApplicationInitializer() {
|
||||
@Override
|
||||
public Set<SessionTrackingMode> getSessionTrackingModes() {
|
||||
return Collections.singleton(SessionTrackingMode.SSL);
|
||||
}
|
||||
}.onStartup(context);
|
||||
verify(context).addFilter(eq("springSecurityFilterChain"), proxyCaptor.capture());
|
||||
assertProxyDefaults(proxyCaptor.getValue());
|
||||
verify(context).setSessionTrackingModes(modesCaptor.capture());
|
||||
Set<SessionTrackingMode> modes = modesCaptor.getValue();
|
||||
assertThat(modes).hasSize(1);
|
||||
assertThat(modes).containsExactly(SessionTrackingMode.SSL);
|
||||
|
||||
+32
-169
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,8 +20,6 @@ import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.mock.web.MockCookie;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
@@ -31,10 +29,9 @@ import static org.springframework.security.web.csrf.CsrfTokenAssert.assertThatCs
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @author Alex Montoya
|
||||
* @since 4.1
|
||||
*/
|
||||
class CookieCsrfTokenRepositoryTests {
|
||||
public class CookieCsrfTokenRepositoryTests {
|
||||
|
||||
CookieCsrfTokenRepository repository;
|
||||
|
||||
@@ -43,7 +40,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
MockHttpServletRequest request;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
public void setup() {
|
||||
this.repository = new CookieCsrfTokenRepository();
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.response = new MockHttpServletResponse();
|
||||
@@ -51,7 +48,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateToken() {
|
||||
public void generateToken() {
|
||||
CsrfToken generateToken = this.repository.generateToken(this.request);
|
||||
assertThat(generateToken).isNotNull();
|
||||
assertThat(generateToken.getHeaderName()).isEqualTo(CookieCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME);
|
||||
@@ -60,7 +57,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateTokenCustom() {
|
||||
public void generateTokenCustom() {
|
||||
String headerName = "headerName";
|
||||
String parameterName = "paramName";
|
||||
this.repository.setHeaderName(headerName);
|
||||
@@ -73,7 +70,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveToken() {
|
||||
public void saveToken() {
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
@@ -82,11 +79,11 @@ class CookieCsrfTokenRepositoryTests {
|
||||
assertThat(tokenCookie.getPath()).isEqualTo(this.request.getContextPath());
|
||||
assertThat(tokenCookie.getSecure()).isEqualTo(this.request.isSecure());
|
||||
assertThat(tokenCookie.getValue()).isEqualTo(token.getToken());
|
||||
assertThat(tokenCookie.isHttpOnly()).isTrue();
|
||||
assertThat(tokenCookie.isHttpOnly()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenSecure() {
|
||||
public void saveTokenSecure() {
|
||||
this.request.setSecure(true);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
@@ -95,7 +92,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenSecureFlagTrue() {
|
||||
public void saveTokenSecureFlagTrue() {
|
||||
this.request.setSecure(false);
|
||||
this.repository.setSecure(Boolean.TRUE);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
@@ -105,17 +102,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenSecureFlagTrueUsingCustomizer() {
|
||||
this.request.setSecure(false);
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.secure(Boolean.TRUE));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie.getSecure()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenSecureFlagFalse() {
|
||||
public void saveTokenSecureFlagFalse() {
|
||||
this.request.setSecure(true);
|
||||
this.repository.setSecure(Boolean.FALSE);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
@@ -125,17 +112,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenSecureFlagFalseUsingCustomizer() {
|
||||
this.request.setSecure(true);
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.secure(Boolean.FALSE));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie.getSecure()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenNull() {
|
||||
public void saveTokenNull() {
|
||||
this.request.setSecure(true);
|
||||
this.repository.saveToken(null, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
@@ -147,7 +124,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenHttpOnlyTrue() {
|
||||
public void saveTokenHttpOnlyTrue() {
|
||||
this.repository.setCookieHttpOnly(true);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
@@ -156,16 +133,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenHttpOnlyTrueUsingCustomizer() {
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.httpOnly(true));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie.isHttpOnly()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenHttpOnlyFalse() {
|
||||
public void saveTokenHttpOnlyFalse() {
|
||||
this.repository.setCookieHttpOnly(false);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
@@ -174,16 +142,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenHttpOnlyFalseUsingCustomizer() {
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.httpOnly(false));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie.isHttpOnly()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithHttpOnlyFalse() {
|
||||
public void saveTokenWithHttpOnlyFalse() {
|
||||
this.repository = CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
@@ -192,7 +151,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenCustomPath() {
|
||||
public void saveTokenCustomPath() {
|
||||
String customPath = "/custompath";
|
||||
this.repository.setCookiePath(customPath);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
@@ -202,7 +161,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenEmptyCustomPath() {
|
||||
public void saveTokenEmptyCustomPath() {
|
||||
String customPath = "";
|
||||
this.repository.setCookiePath(customPath);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
@@ -212,7 +171,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenNullCustomPath() {
|
||||
public void saveTokenNullCustomPath() {
|
||||
String customPath = null;
|
||||
this.repository.setCookiePath(customPath);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
@@ -222,7 +181,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithCookieDomain() {
|
||||
public void saveTokenWithCookieDomain() {
|
||||
String domainName = "example.com";
|
||||
this.repository.setCookieDomain(domainName);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
@@ -232,17 +191,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithCookieDomainUsingCustomizer() {
|
||||
String domainName = "example.com";
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.domain(domainName));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie.getDomain()).isEqualTo(domainName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithCookieMaxAge() {
|
||||
public void saveTokenWithCookieMaxAge() {
|
||||
int maxAge = 1200;
|
||||
this.repository.setCookieMaxAge(maxAge);
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
@@ -252,75 +201,24 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithCookieMaxAgeUsingCustomizer() {
|
||||
int maxAge = 1200;
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.maxAge(maxAge));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie.getMaxAge()).isEqualTo(maxAge);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithSameSiteNull() {
|
||||
String sameSitePolicy = null;
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.sameSite(sameSitePolicy));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(((MockCookie) tokenCookie).getSameSite()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithSameSiteStrict() {
|
||||
String sameSitePolicy = "Strict";
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.sameSite(sameSitePolicy));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(((MockCookie) tokenCookie).getSameSite()).isEqualTo(sameSitePolicy);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWithSameSiteLax() {
|
||||
String sameSitePolicy = "Lax";
|
||||
this.repository.setCookieCustomizer((customizer) -> customizer.sameSite(sameSitePolicy));
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(((MockCookie) tokenCookie).getSameSite()).isEqualTo(sameSitePolicy);
|
||||
}
|
||||
|
||||
// gh-13075
|
||||
@Test
|
||||
void saveTokenWithExistingSetCookieThenDoesNotOverwrite() {
|
||||
this.response.setHeader(HttpHeaders.SET_COOKIE, "MyCookie=test");
|
||||
this.repository = new CookieCsrfTokenRepository();
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
assertThat(this.response.getCookie("MyCookie")).isNotNull();
|
||||
assertThat(this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenNoCookiesNull() {
|
||||
public void loadTokenNoCookiesNull() {
|
||||
assertThat(this.repository.loadToken(this.request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenCookieIncorrectNameNull() {
|
||||
public void loadTokenCookieIncorrectNameNull() {
|
||||
this.request.setCookies(new Cookie("other", "name"));
|
||||
assertThat(this.repository.loadToken(this.request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenCookieValueEmptyString() {
|
||||
public void loadTokenCookieValueEmptyString() {
|
||||
this.request.setCookies(new Cookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, ""));
|
||||
assertThat(this.repository.loadToken(this.request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadToken() {
|
||||
public void loadToken() {
|
||||
CsrfToken generateToken = this.repository.generateToken(this.request);
|
||||
this.request
|
||||
.setCookies(new Cookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, generateToken.getToken()));
|
||||
@@ -332,7 +230,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenCustom() {
|
||||
public void loadTokenCustom() {
|
||||
String cookieName = "cookieName";
|
||||
String value = "value";
|
||||
String headerName = "headerName";
|
||||
@@ -349,7 +247,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadDeferredTokenWhenDoesNotExistThenGeneratedAndSaved() {
|
||||
public void loadDeferredTokenWhenDoesNotExistThenGeneratedAndSaved() {
|
||||
DeferredCsrfToken deferredCsrfToken = this.repository.loadDeferredToken(this.request, this.response);
|
||||
CsrfToken csrfToken = deferredCsrfToken.get();
|
||||
assertThat(csrfToken).isNotNull();
|
||||
@@ -365,7 +263,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadDeferredTokenWhenExistsAndNullSavedThenGeneratedAndSaved() {
|
||||
public void loadDeferredTokenWhenExistsAndNullSavedThenGeneratedAndSaved() {
|
||||
CsrfToken generatedToken = this.repository.generateToken(this.request);
|
||||
this.request
|
||||
.setCookies(new Cookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, generatedToken.getToken()));
|
||||
@@ -378,7 +276,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadDeferredTokenWhenExistsAndNullSavedAndNonNullSavedThenLoaded() {
|
||||
public void loadDeferredTokenWhenExistsAndNullSavedAndNonNullSavedThenLoaded() {
|
||||
CsrfToken generatedToken = this.repository.generateToken(this.request);
|
||||
this.request
|
||||
.setCookies(new Cookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, generatedToken.getToken()));
|
||||
@@ -391,7 +289,7 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadDeferredTokenWhenExistsThenLoaded() {
|
||||
public void loadDeferredTokenWhenExistsThenLoaded() {
|
||||
CsrfToken generatedToken = this.repository.generateToken(this.request);
|
||||
this.request
|
||||
.setCookies(new Cookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, generatedToken.getToken()));
|
||||
@@ -402,57 +300,22 @@ class CookieCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void cookieCustomizer() {
|
||||
String domainName = "example.com";
|
||||
String customPath = "/custompath";
|
||||
String sameSitePolicy = "Strict";
|
||||
this.repository.setCookieCustomizer((customizer) -> {
|
||||
customizer.domain(domainName);
|
||||
customizer.secure(false);
|
||||
customizer.path(customPath);
|
||||
customizer.sameSite(sameSitePolicy);
|
||||
});
|
||||
CsrfToken token = this.repository.generateToken(this.request);
|
||||
this.repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie).isNotNull();
|
||||
assertThat(tokenCookie.getMaxAge()).isEqualTo(-1);
|
||||
assertThat(tokenCookie.getDomain()).isEqualTo(domainName);
|
||||
assertThat(tokenCookie.getPath()).isEqualTo(customPath);
|
||||
assertThat(tokenCookie.isHttpOnly()).isEqualTo(Boolean.TRUE);
|
||||
assertThat(((MockCookie) tokenCookie).getSameSite()).isEqualTo(sameSitePolicy);
|
||||
}
|
||||
|
||||
// gh-13659
|
||||
@Test
|
||||
void withHttpOnlyFalseWhenCookieCustomizerThenStillDefaultsToFalse() {
|
||||
CookieCsrfTokenRepository repository = CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||
repository.setCookieCustomizer((customizer) -> customizer.maxAge(1000));
|
||||
CsrfToken token = repository.generateToken(this.request);
|
||||
repository.saveToken(token, this.request, this.response);
|
||||
Cookie tokenCookie = this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||
assertThat(tokenCookie).isNotNull();
|
||||
assertThat(tokenCookie.getMaxAge()).isEqualTo(1000);
|
||||
assertThat(tokenCookie.isHttpOnly()).isEqualTo(Boolean.FALSE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void setCookieNameNullIllegalArgumentException() {
|
||||
public void setCookieNameNullIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setCookieName(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setParameterNameNullIllegalArgumentException() {
|
||||
public void setParameterNameNullIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setParameterName(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setHeaderNameNullIllegalArgumentException() {
|
||||
public void setHeaderNameNullIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setHeaderName(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setCookieMaxAgeZeroIllegalArgumentException() {
|
||||
public void setCookieMaxAgeZeroIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setCookieMaxAge(0));
|
||||
}
|
||||
|
||||
|
||||
+1
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -208,14 +208,6 @@ public class XorCsrfTokenRequestAttributeHandlerTests {
|
||||
assertThat(tokenValue).isEqualTo(this.token.getToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveCsrfTokenIsInvalidThenReturnsNull() {
|
||||
this.request.setParameter(this.token.getParameterName(), XOR_CSRF_TOKEN_VALUE);
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("headerName", "paramName", "a");
|
||||
String tokenValue = this.handler.resolveCsrfTokenValue(this.request, csrfToken);
|
||||
assertThat(tokenValue).isNull();
|
||||
}
|
||||
|
||||
private static Answer<Void> fillByteArray() {
|
||||
return (invocation) -> {
|
||||
byte[] bytes = invocation.getArgument(0);
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class CacheControlHeadersWriterTests {
|
||||
@Test
|
||||
public void writeHeaders() {
|
||||
this.writer.writeHeaders(this.request, this.response);
|
||||
assertThat(this.response.getHeaderNames()).hasSize(3);
|
||||
assertThat(this.response.getHeaderNames().size()).isEqualTo(3);
|
||||
assertThat(this.response.getHeaderValues("Cache-Control"))
|
||||
.containsOnly("no-cache, no-store, max-age=0, must-revalidate");
|
||||
assertThat(this.response.getHeaderValues("Pragma")).containsOnly("no-cache");
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ public class HstsHeaderWriterTests {
|
||||
public void writeHeadersInsecureRequestDoesNotWriteHeader() {
|
||||
this.request.setSecure(false);
|
||||
this.writer.writeHeaders(this.request, this.response);
|
||||
assertThat(this.response.getHeaderNames()).isEmpty();
|
||||
assertThat(this.response.getHeaderNames().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ public class FrameOptionsHeaderWriterTests {
|
||||
public void writeHeadersAllowFromReturnsNull() {
|
||||
this.writer = new XFrameOptionsHeaderWriter(this.strategy);
|
||||
this.writer.writeHeaders(this.request, this.response);
|
||||
assertThat(this.response.getHeaderNames()).isEmpty();
|
||||
assertThat(this.response.getHeaderNames().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
@@ -131,7 +131,7 @@ public final class ResolvableMethod {
|
||||
|
||||
private static final SpringObjenesis objenesis = new SpringObjenesis();
|
||||
|
||||
private static final ParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
private static final ParameterNameDiscoverer nameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
|
||||
private final Method method;
|
||||
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class DefaultSavedRequestTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("If-None-Match", "somehashvalue");
|
||||
DefaultSavedRequest saved = new DefaultSavedRequest(request, new MockPortResolver(8080, 8443));
|
||||
assertThat(saved.getHeaderValues("if-none-match")).isEmpty();
|
||||
assertThat(saved.getHeaderValues("if-none-match").isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
// SEC-3082
|
||||
|
||||
+6
-15
@@ -24,7 +24,6 @@ import java.util.Locale;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.web.PortResolverImpl;
|
||||
|
||||
@@ -43,21 +42,22 @@ public class SavedRequestAwareWrapperTests {
|
||||
@Test
|
||||
public void savedRequestCookiesAreIgnored() {
|
||||
MockHttpServletRequest newRequest = new MockHttpServletRequest();
|
||||
newRequest.setCookies(new Cookie("cookie", "fromnew"));
|
||||
newRequest.setCookies(new Cookie[] { new Cookie("cookie", "fromnew") });
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.setCookies(new Cookie("cookie", "fromsaved"));
|
||||
savedRequest.setCookies(new Cookie[] { new Cookie("cookie", "fromsaved") });
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, newRequest);
|
||||
assertThat(wrapper.getCookies()).hasSize(1);
|
||||
assertThat(wrapper.getCookies()[0].getValue()).isEqualTo("fromnew");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void savedRequesthHeaderIsReturnedIfSavedRequestIsSet() {
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.addHeader("header", "savedheader");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, new MockHttpServletRequest());
|
||||
assertThat(wrapper.getHeader("nonexistent")).isNull();
|
||||
Enumeration<String> headers = wrapper.getHeaders("nonexistent");
|
||||
Enumeration headers = wrapper.getHeaders("nonexistent");
|
||||
assertThat(headers.hasMoreElements()).isFalse();
|
||||
assertThat(wrapper.getHeader("Header")).isEqualTo("savedheader");
|
||||
headers = wrapper.getHeaders("heaDer");
|
||||
@@ -97,7 +97,7 @@ public class SavedRequestAwareWrapperTests {
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, wrappedRequest);
|
||||
assertThat(wrapper.getParameterValues("action")).hasSize(1);
|
||||
assertThat(wrapper.getParameterMap()).hasSize(1);
|
||||
assertThat(wrapper.getParameterMap().get("action")).hasSize(1);
|
||||
assertThat(((String[]) wrapper.getParameterMap().get("action"))).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,7 +127,7 @@ public class SavedRequestAwareWrapperTests {
|
||||
wrappedRequest.setParameter("action", "bar");
|
||||
assertThat(wrapper.getParameterValues("action")).isEqualTo(new Object[] { "bar", "foo" });
|
||||
// Check map is consistent
|
||||
String[] valuesFromMap = wrapper.getParameterMap().get("action");
|
||||
String[] valuesFromMap = (String[]) wrapper.getParameterMap().get("action");
|
||||
assertThat(valuesFromMap).hasSize(2);
|
||||
assertThat(valuesFromMap[0]).isEqualTo("bar");
|
||||
}
|
||||
@@ -169,13 +169,4 @@ public class SavedRequestAwareWrapperTests {
|
||||
assertThat(wrapper.getIntHeader("nonexistent")).isEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctContentTypeIsReturned() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/notused");
|
||||
request.setContentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(request, new MockHttpServletRequest("GET", "/notused"));
|
||||
assertThat(wrapper.getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -17,23 +17,17 @@
|
||||
package org.springframework.security.web.server.context;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
import reactor.test.StepVerifier;
|
||||
import reactor.test.publisher.TestPublisher;
|
||||
import reactor.util.context.Context;
|
||||
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -125,32 +119,4 @@ public class ReactorContextWebFilterTests {
|
||||
StepVerifier.create(filter).expectAccessibleContext().hasKey(contextKey).then().verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterWhenThreadFactoryIsPlatformThenSecurityContextLoaded() {
|
||||
ThreadFactory threadFactory = Executors.defaultThreadFactory();
|
||||
assertSecurityContextLoaded(threadFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void filterWhenThreadFactoryIsVirtualThenSecurityContextLoaded() {
|
||||
ThreadFactory threadFactory = new VirtualThreadTaskExecutor().getVirtualThreadFactory();
|
||||
assertSecurityContextLoaded(threadFactory);
|
||||
}
|
||||
|
||||
private void assertSecurityContextLoaded(ThreadFactory threadFactory) {
|
||||
SecurityContextImpl context = new SecurityContextImpl(this.principal);
|
||||
given(this.repository.load(any())).willReturn(Mono.just(context));
|
||||
// @formatter:off
|
||||
WebFilter subscribeOnThreadFactory = (exchange, chain) -> chain.filter(exchange)
|
||||
.subscribeOn(Schedulers.newSingle(threadFactory));
|
||||
WebFilter assertSecurityContext = (exchange, chain) -> ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.doOnSuccess((authentication) -> assertThat(authentication).isSameAs(this.principal))
|
||||
.then(chain.filter(exchange));
|
||||
// @formatter:on
|
||||
this.handler = WebTestHandler.bindToWebFilters(subscribeOnThreadFactory, this.filter, assertSecurityContext);
|
||||
this.handler.exchange(this.exchange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -17,25 +17,17 @@
|
||||
package org.springframework.security.web.server.context;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.test.web.reactive.server.WebTestHandler;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.handler.DefaultWebFilterChain;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -88,31 +80,4 @@ public class SecurityContextServerWebExchangeWebFilterTests {
|
||||
StepVerifier.create(result).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterWhenThreadFactoryIsPlatformThenContextPopulated() {
|
||||
ThreadFactory threadFactory = Executors.defaultThreadFactory();
|
||||
assertPrincipalPopulated(threadFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void filterWhenThreadFactoryIsVirtualThenContextPopulated() {
|
||||
ThreadFactory threadFactory = new VirtualThreadTaskExecutor().getVirtualThreadFactory();
|
||||
assertPrincipalPopulated(threadFactory);
|
||||
}
|
||||
|
||||
private void assertPrincipalPopulated(ThreadFactory threadFactory) {
|
||||
// @formatter:off
|
||||
WebFilter subscribeOnThreadFactory = (exchange, chain) -> chain.filter(exchange)
|
||||
.contextWrite(ReactiveSecurityContextHolder.withAuthentication(this.principal))
|
||||
.subscribeOn(Schedulers.newSingle(threadFactory));
|
||||
WebFilter assertPrincipal = (exchange, chain) -> exchange.getPrincipal()
|
||||
.doOnSuccess((principal) -> assertThat(principal).isSameAs(this.principal))
|
||||
.then(chain.filter(exchange));
|
||||
// @formatter:on
|
||||
WebTestHandler handler = WebTestHandler.bindToWebFilters(subscribeOnThreadFactory, this.filter,
|
||||
assertPrincipal);
|
||||
handler.exchange(this.exchange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
-105
@@ -18,7 +18,6 @@ package org.springframework.security.web.server.csrf;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -36,10 +35,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Eric Deandrea
|
||||
* @author Thomas Vitale
|
||||
* @author Alonso Araya
|
||||
* @author Alex Montoya
|
||||
* @since 5.1
|
||||
*/
|
||||
class CookieServerCsrfTokenRepositoryTests {
|
||||
public class CookieServerCsrfTokenRepositoryTests {
|
||||
|
||||
private CookieServerCsrfTokenRepository csrfTokenRepository;
|
||||
|
||||
@@ -63,122 +61,78 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
|
||||
private String expectedCookieValue = "csrfToken";
|
||||
|
||||
private String expectedSameSitePolicy = null;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
public void setUp() {
|
||||
this.csrfTokenRepository = new CookieServerCsrfTokenRepository();
|
||||
this.request = MockServerHttpRequest.get("/someUri");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateTokenWhenDefaultThenDefaults() {
|
||||
public void generateTokenWhenDefaultThenDefaults() {
|
||||
generateTokenAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateTokenWhenCustomHeaderThenCustomHeader() {
|
||||
public void generateTokenWhenCustomHeaderThenCustomHeader() {
|
||||
setExpectedHeaderName("someHeader");
|
||||
generateTokenAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateTokenWhenCustomParameterThenCustomParameter() {
|
||||
public void generateTokenWhenCustomParameterThenCustomParameter() {
|
||||
setExpectedParameterName("someParam");
|
||||
generateTokenAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateTokenWhenCustomHeaderAndParameterThenCustomHeaderAndParameter() {
|
||||
public void generateTokenWhenCustomHeaderAndParameterThenCustomHeaderAndParameter() {
|
||||
setExpectedHeaderName("someHeader");
|
||||
setExpectedParameterName("someParam");
|
||||
generateTokenAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenNoSubscriptionThenNotWritten() {
|
||||
public void saveTokenWhenNoSubscriptionThenNotWritten() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken());
|
||||
assertThat(exchange.getResponse().getCookies().getFirst(this.expectedCookieName)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenDefaultThenDefaults() {
|
||||
public void saveTokenWhenDefaultThenDefaults() {
|
||||
saveAndAssertExpectedValues(createToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenNullThenDeletes() {
|
||||
public void saveTokenWhenNullThenDeletes() {
|
||||
saveAndAssertExpectedValues(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenHttpOnlyFalseThenHttpOnlyFalse() {
|
||||
public void saveTokenWhenHttpOnlyFalseThenHttpOnlyFalse() {
|
||||
setExpectedHttpOnly(false);
|
||||
saveAndAssertExpectedValues(createToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenCookieMaxAgeThenCookieMaxAge() {
|
||||
public void saveTokenWhenCookieMaxAgeThenCookieMaxAge() {
|
||||
setExpectedCookieMaxAge(3600);
|
||||
saveAndAssertExpectedValues(createToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSameSiteThenCookieSameSite() {
|
||||
setExpectedSameSitePolicy("Lax");
|
||||
saveAndAssertExpectedValues(createToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenCustomPropertiesThenCustomProperties() {
|
||||
public void saveTokenWhenCustomPropertiesThenCustomProperties() {
|
||||
setExpectedDomain("spring.io");
|
||||
setExpectedCookieName("csrfCookie");
|
||||
setExpectedPath("/some/path");
|
||||
setExpectedHeaderName("headerName");
|
||||
setExpectedParameterName("paramName");
|
||||
setExpectedSameSitePolicy("Strict");
|
||||
setExpectedCookieMaxAge(3600);
|
||||
saveAndAssertExpectedValues(createToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenCustomPropertiesThenCustomPropertiesUsingCustomizer() {
|
||||
String expectedDomain = "spring.io";
|
||||
int expectedMaxAge = 3600;
|
||||
String expectedPath = "/some/path";
|
||||
String expectedSameSite = "Strict";
|
||||
|
||||
setExpectedCookieName("csrfCookie");
|
||||
|
||||
setExpectedHeaderName("headerName");
|
||||
setExpectedParameterName("paramName");
|
||||
|
||||
CsrfToken token = createToken();
|
||||
|
||||
this.csrfTokenRepository.setCookieCustomizer((customizer) -> {
|
||||
customizer.domain(expectedDomain);
|
||||
customizer.maxAge(expectedMaxAge);
|
||||
customizer.path(expectedPath);
|
||||
customizer.sameSite(expectedSameSite);
|
||||
});
|
||||
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.saveToken(exchange, token).block();
|
||||
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.getMaxAge()).isEqualTo(Duration.of(expectedMaxAge, ChronoUnit.SECONDS));
|
||||
assertThat(cookie.getDomain()).isEqualTo(expectedDomain);
|
||||
assertThat(cookie.getPath()).isEqualTo(expectedPath);
|
||||
assertThat(cookie.getSameSite()).isEqualTo(expectedSameSite);
|
||||
assertThat(cookie.isSecure()).isEqualTo(this.expectedSecure);
|
||||
assertThat(cookie.isHttpOnly()).isEqualTo(this.expectedHttpOnly);
|
||||
assertThat(cookie.getName()).isEqualTo(this.expectedCookieName);
|
||||
assertThat(cookie.getValue()).isEqualTo(this.expectedCookieValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSslInfoPresentThenSecure() {
|
||||
public void saveTokenWhenSslInfoPresentThenSecure() {
|
||||
this.request.sslInfo(new MockSslInfo());
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken()).block();
|
||||
@@ -188,7 +142,7 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSslInfoNullThenNotSecure() {
|
||||
public void saveTokenWhenSslInfoNullThenNotSecure() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken()).block();
|
||||
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
|
||||
@@ -197,7 +151,7 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSecureFlagTrueThenSecure() {
|
||||
public void saveTokenWhenSecureFlagTrueThenSecure() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.setSecure(true);
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken()).block();
|
||||
@@ -207,17 +161,7 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSecureFlagTrueThenSecureUsingCustomizer() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.setCookieCustomizer((customizer) -> customizer.secure(true));
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken()).block();
|
||||
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.isSecure()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSecureFlagFalseThenNotSecure() {
|
||||
public void saveTokenWhenSecureFlagFalseThenNotSecure() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.setSecure(false);
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken()).block();
|
||||
@@ -227,17 +171,7 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSecureFlagFalseThenNotSecureUsingCustomizer() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.csrfTokenRepository.setCookieCustomizer((customizer) -> customizer.secure(false));
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken()).block();
|
||||
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.isSecure()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSecureFlagFalseAndSslInfoThenNotSecure() {
|
||||
public void saveTokenWhenSecureFlagFalseAndSslInfoThenNotSecure() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.request.sslInfo(new MockSslInfo());
|
||||
this.csrfTokenRepository.setSecure(false);
|
||||
@@ -248,23 +182,12 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveTokenWhenSecureFlagFalseAndSslInfoThenNotSecureUsingCustomizer() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
this.request.sslInfo(new MockSslInfo());
|
||||
this.csrfTokenRepository.setCookieCustomizer((customizer) -> customizer.secure(false));
|
||||
this.csrfTokenRepository.saveToken(exchange, createToken()).block();
|
||||
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.isSecure()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenWhenCookieExistThenTokenFound() {
|
||||
public void loadTokenWhenCookieExistThenTokenFound() {
|
||||
loadAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenWhenCustomThenTokenFound() {
|
||||
public void loadTokenWhenCustomThenTokenFound() {
|
||||
setExpectedParameterName("paramName");
|
||||
setExpectedHeaderName("headerName");
|
||||
setExpectedCookieName("csrfCookie");
|
||||
@@ -272,20 +195,20 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenWhenNoCookiesThenNullToken() {
|
||||
public void loadTokenWhenNoCookiesThenNullToken() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
|
||||
CsrfToken csrfToken = this.csrfTokenRepository.loadToken(exchange).block();
|
||||
assertThat(csrfToken).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenWhenCookieExistsWithNoValue() {
|
||||
public void loadTokenWhenCookieExistsWithNoValue() {
|
||||
setExpectedCookieValue("");
|
||||
loadAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadTokenWhenCookieExistsWithNullValue() {
|
||||
public void loadTokenWhenCookieExistsWithNullValue() {
|
||||
setExpectedCookieValue(null);
|
||||
loadAndAssertExpectedValues();
|
||||
}
|
||||
@@ -325,11 +248,6 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
this.expectedMaxAge = Duration.ofSeconds(expectedCookieMaxAge);
|
||||
}
|
||||
|
||||
private void setExpectedSameSitePolicy(String sameSitePolicy) {
|
||||
this.csrfTokenRepository.setCookieCustomizer((customizer) -> customizer.sameSite(sameSitePolicy));
|
||||
this.expectedSameSitePolicy = sameSitePolicy;
|
||||
}
|
||||
|
||||
private void setExpectedCookieValue(String expectedCookieValue) {
|
||||
this.expectedCookieValue = expectedCookieValue;
|
||||
}
|
||||
@@ -366,7 +284,6 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
assertThat(cookie.isHttpOnly()).isEqualTo(this.expectedHttpOnly);
|
||||
assertThat(cookie.getName()).isEqualTo(this.expectedCookieName);
|
||||
assertThat(cookie.getValue()).isEqualTo(this.expectedCookieValue);
|
||||
assertThat(cookie.getSameSite()).isEqualTo(this.expectedSameSitePolicy);
|
||||
}
|
||||
|
||||
private void generateTokenAndAssertExpectedValues() {
|
||||
|
||||
+1
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -188,18 +188,6 @@ public class XorServerCsrfTokenRequestAttributeHandlerTests {
|
||||
StepVerifier.create(csrfToken).expectNext(this.token.getToken()).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveCsrfTokenIsInvalidThenReturnsNull() {
|
||||
this.exchange = MockServerWebExchange
|
||||
.builder(MockServerHttpRequest.post("/")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.body(this.token.getParameterName() + "=" + XOR_CSRF_TOKEN_VALUE))
|
||||
.build();
|
||||
CsrfToken token = new DefaultCsrfToken("headerName", "paramName", "a");
|
||||
Mono<String> csrfToken = this.handler.resolveCsrfTokenValue(this.exchange, token);
|
||||
assertThat(csrfToken.block()).isNull();
|
||||
}
|
||||
|
||||
private static Answer<Void> fillByteArray() {
|
||||
return (invocation) -> {
|
||||
byte[] bytes = invocation.getArgument(0);
|
||||
|
||||
+2
-2
@@ -46,7 +46,7 @@ public class CookieServerRequestCacheTests {
|
||||
.from(MockServerHttpRequest.get("/secured/").accept(MediaType.TEXT_HTML));
|
||||
this.cache.saveRequest(exchange).block();
|
||||
MultiValueMap<String, ResponseCookie> cookies = exchange.getResponse().getCookies();
|
||||
assertThat(cookies).hasSize(1);
|
||||
assertThat(cookies.size()).isEqualTo(1);
|
||||
ResponseCookie cookie = cookies.getFirst("REDIRECT_URI");
|
||||
assertThat(cookie).isNotNull();
|
||||
String encodedRedirectUrl = Base64.getEncoder().encodeToString("/secured/".getBytes());
|
||||
@@ -60,7 +60,7 @@ public class CookieServerRequestCacheTests {
|
||||
.from(MockServerHttpRequest.get("/secured/").queryParam("key", "value").accept(MediaType.TEXT_HTML));
|
||||
this.cache.saveRequest(exchange).block();
|
||||
MultiValueMap<String, ResponseCookie> cookies = exchange.getResponse().getCookies();
|
||||
assertThat(cookies).hasSize(1);
|
||||
assertThat(cookies.size()).isEqualTo(1);
|
||||
ResponseCookie cookie = cookies.getFirst("REDIRECT_URI");
|
||||
assertThat(cookie).isNotNull();
|
||||
String encodedRedirectUrl = Base64.getEncoder().encodeToString("/secured/?key=value".getBytes());
|
||||
|
||||
+1
-69
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,10 +20,8 @@ import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -31,7 +29,6 @@ import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
@@ -49,11 +46,9 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @author Rob Winch
|
||||
* @author Mark Chesney
|
||||
*/
|
||||
public class SessionManagementFilterTests {
|
||||
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
public void clearContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
@@ -179,69 +174,6 @@ public class SessionManagementFilterTests {
|
||||
assertThat(response.getRedirectedUrl()).isEqualTo("/requested");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseIsRedirectedToRequestedUrlIfContextPathIsSetAndSessionIsInvalid() throws Exception {
|
||||
// given
|
||||
DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
redirectStrategy.setContextRelative(true);
|
||||
RequestedUrlRedirectInvalidSessionStrategy invalidSessionStrategy = new RequestedUrlRedirectInvalidSessionStrategy();
|
||||
invalidSessionStrategy.setCreateNewSession(true);
|
||||
invalidSessionStrategy.setRedirectStrategy(redirectStrategy);
|
||||
SecurityContextRepository securityContextRepository = mock(SecurityContextRepository.class);
|
||||
SessionAuthenticationStrategy sessionAuthenticationStrategy = mock(SessionAuthenticationStrategy.class);
|
||||
SessionManagementFilter filter = new SessionManagementFilter(securityContextRepository,
|
||||
sessionAuthenticationStrategy);
|
||||
filter.setInvalidSessionStrategy(invalidSessionStrategy);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContextPath("/context");
|
||||
request.setRequestedSessionId("xxx");
|
||||
request.setRequestedSessionIdValid(false);
|
||||
request.setRequestURI("/context/requested");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
||||
// when
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
// then
|
||||
verify(securityContextRepository).containsContext(request);
|
||||
verifyNoMoreInteractions(securityContextRepository, sessionAuthenticationStrategy, chain);
|
||||
assertThat(response.isCommitted()).isTrue();
|
||||
assertThat(response.getRedirectedUrl()).isEqualTo("/context/requested");
|
||||
assertThat(response.getStatus()).isEqualTo(302);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseIsRedirectedToRequestedUrlIfStatusCodeIsSetAndSessionIsInvalid() throws Exception {
|
||||
// given
|
||||
DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
redirectStrategy.setStatusCode(HttpStatus.TEMPORARY_REDIRECT);
|
||||
RequestedUrlRedirectInvalidSessionStrategy invalidSessionStrategy = new RequestedUrlRedirectInvalidSessionStrategy();
|
||||
invalidSessionStrategy.setCreateNewSession(true);
|
||||
invalidSessionStrategy.setRedirectStrategy(redirectStrategy);
|
||||
SecurityContextRepository securityContextRepository = mock(SecurityContextRepository.class);
|
||||
SessionAuthenticationStrategy sessionAuthenticationStrategy = mock(SessionAuthenticationStrategy.class);
|
||||
SessionManagementFilter filter = new SessionManagementFilter(securityContextRepository,
|
||||
sessionAuthenticationStrategy);
|
||||
filter.setInvalidSessionStrategy(invalidSessionStrategy);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestedSessionId("xxx");
|
||||
request.setRequestedSessionIdValid(false);
|
||||
request.setRequestURI("/requested");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
||||
// when
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
// then
|
||||
verify(securityContextRepository).containsContext(request);
|
||||
verifyNoMoreInteractions(securityContextRepository, sessionAuthenticationStrategy, chain);
|
||||
assertThat(response.isCommitted()).isTrue();
|
||||
assertThat(response.getRedirectedUrl()).isEqualTo("/requested");
|
||||
assertThat(response.getStatus()).isEqualTo(307);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAuthenticationTrustResolver() throws Exception {
|
||||
AuthenticationTrustResolver trustResolver = mock(AuthenticationTrustResolver.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -62,7 +62,7 @@ public class TextEscapeUtilsTests {
|
||||
|
||||
@Test
|
||||
public void undefinedSurrogatePairIsIgnored() {
|
||||
assertThat(TextEscapeUtils.escapeEntities("abc\uDBFF\uDFFFa")).isEqualTo("abca");
|
||||
assertThat(TextEscapeUtils.escapeEntities("abc\uD888\uDC00a")).isEqualTo("abca");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.security.web.util.matcher;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -27,8 +26,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher.MatchResult;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
|
||||
@@ -126,30 +123,4 @@ public class AndRequestMatcherTests {
|
||||
assertThat(this.matcher.matches(this.request)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matcherWhenMatchersHavePlaceholdersThenPropagatesMatches() {
|
||||
this.matcher = new AndRequestMatcher(this.delegate, this.delegate2);
|
||||
|
||||
given(this.delegate.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "value")));
|
||||
given(this.delegate2.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "othervalue")));
|
||||
MatchResult result = this.matcher.matcher(this.request);
|
||||
assertThat(result.getVariables()).containsExactlyEntriesOf(Map.of("param", "othervalue"));
|
||||
|
||||
given(this.delegate.matcher(this.request)).willReturn(MatchResult.match());
|
||||
given(this.delegate2.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "value")));
|
||||
result = this.matcher.matcher(this.request);
|
||||
assertThat(result.getVariables()).containsExactlyEntriesOf(Map.of("param", "value"));
|
||||
|
||||
given(this.delegate.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "value")));
|
||||
given(this.delegate2.matcher(this.request)).willReturn(MatchResult.notMatch());
|
||||
result = this.matcher.matcher(this.request);
|
||||
assertThat(result.getVariables()).isEmpty();
|
||||
|
||||
given(this.delegate.matcher(this.request)).willReturn(MatchResult.match(Map.of("otherparam", "value")));
|
||||
given(this.delegate2.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "value")));
|
||||
result = this.matcher.matcher(this.request);
|
||||
assertThat(result.getVariables())
|
||||
.containsExactlyInAnyOrderEntriesOf(Map.of("otherparam", "value", "param", "value"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ public class MediaTypeRequestMatcherTests {
|
||||
|
||||
@Test
|
||||
public void constructorWhenEmptyMediaTypeThenIAE() {
|
||||
assertThatIllegalArgumentException().isThrownBy(MediaTypeRequestMatcher::new);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new MediaTypeRequestMatcher());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.security.web.util.matcher;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -27,13 +26,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher.MatchResult;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -126,26 +122,4 @@ public class OrRequestMatcherTests {
|
||||
assertThat(this.matcher.matches(this.request)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matcherWhenMatchersHavePlaceholdersThenPropagatesFirstMatch() {
|
||||
this.matcher = new OrRequestMatcher(this.delegate, this.delegate2);
|
||||
|
||||
given(this.delegate.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "value")));
|
||||
given(this.delegate2.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "othervalue")));
|
||||
MatchResult result = this.matcher.matcher(this.request);
|
||||
assertThat(result.getVariables()).containsExactlyEntriesOf(Map.of("param", "value"));
|
||||
verifyNoInteractions(this.delegate2);
|
||||
|
||||
given(this.delegate.matcher(this.request)).willReturn(MatchResult.match());
|
||||
given(this.delegate2.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "value")));
|
||||
result = this.matcher.matcher(this.request);
|
||||
assertThat(result.getVariables()).isEmpty();
|
||||
verifyNoInteractions(this.delegate2);
|
||||
|
||||
given(this.delegate.matcher(this.request)).willReturn(MatchResult.notMatch());
|
||||
given(this.delegate2.matcher(this.request)).willReturn(MatchResult.match(Map.of("param", "value")));
|
||||
result = this.matcher.matcher(this.request);
|
||||
assertThat(result.getVariables()).containsExactlyEntriesOf(Map.of("param", "value"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.web.util.matcher;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestMatchers}.
|
||||
*
|
||||
* @author Christian Schuster
|
||||
*/
|
||||
class RequestMatchersTests {
|
||||
|
||||
@Test
|
||||
void checkAnyOfWhenOneMatchThenMatch() {
|
||||
RequestMatcher composed = RequestMatchers.anyOf((r) -> false, (r) -> true);
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkAnyOfWhenNoneMatchThenNotMatch() {
|
||||
RequestMatcher composed = RequestMatchers.anyOf((r) -> false, (r) -> false);
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkAnyOfWhenEmptyThenNotMatch() {
|
||||
RequestMatcher composed = RequestMatchers.anyOf();
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkAllOfWhenOneNotMatchThenNotMatch() {
|
||||
RequestMatcher composed = RequestMatchers.allOf((r) -> false, (r) -> true);
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkAllOfWhenAllMatchThenMatch() {
|
||||
RequestMatcher composed = RequestMatchers.allOf((r) -> true, (r) -> true);
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkAllOfWhenEmptyThenMatch() {
|
||||
RequestMatcher composed = RequestMatchers.allOf();
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkNotWhenMatchThenNotMatch() {
|
||||
RequestMatcher composed = RequestMatchers.not((r) -> true);
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkNotWhenNotMatchThenMatch() {
|
||||
RequestMatcher composed = RequestMatchers.not((r) -> false);
|
||||
boolean match = composed.matches(null);
|
||||
assertThat(match).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
+6
-6
@@ -11,15 +11,15 @@
|
||||
</constructor-arg>
|
||||
<property name="defaultEntryPoint" ref="defaultAEP"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="firstAEP" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.security.web.AuthenticationEntryPoint" type="java.lang.Class"/>
|
||||
<constructor-arg value="org.springframework.security.web.AuthenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
|
||||
|
||||
|
||||
<bean id="defaultAEP" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.security.web.AuthenticationEntryPoint" type="java.lang.Class"/>
|
||||
<constructor-arg value="org.springframework.security.web.AuthenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
|
||||
|
||||
</beans>
|
||||
|
||||
Reference in New Issue
Block a user