1
0
mirror of synced 2026-08-06 02:08:01 +00:00

Revert unnecessary merges on 6.0.x

This commit removes unnecessary main-branch merges starting from
8750608b5b and adds the following
needed commit(s) that were made afterward:

- 5dce82c48b
This commit is contained in:
Steve Riesenberg
2023-10-31 15:11:45 -05:00
parent e9d4223402
commit 9db33f33c7
676 changed files with 6306 additions and 43249 deletions
@@ -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 {
@@ -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) {
@@ -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();
@@ -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,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>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class SecurityConfig {
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http
* .authorizeHttpRequests((authorize) -&gt; 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,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;
}
}
}
}
@@ -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;
}
/**
@@ -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 {
}
}
@@ -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.");
@@ -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
@@ -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(
@@ -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;
}
@@ -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 "";
}
@@ -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");
@@ -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) {
@@ -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(
@@ -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>
@@ -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);
@@ -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.");
}
}
@@ -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;
@@ -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;
}
@@ -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
@@ -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;
}
@@ -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) {
@@ -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());
}
}
@@ -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;
@@ -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);
@@ -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");
@@ -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");
@@ -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,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;
@@ -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;
}
@@ -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,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;
@@ -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() {
}
}