فهرست منبع

Merge branch '6.2.x' into 6.3.x

Joe Grandja 9 ماه پیش
والد
کامیت
709103e38c
24فایلهای تغییر یافته به همراه96 افزوده شده و 50 حذف شده
  1. 3 1
      cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java
  2. 3 2
      config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java
  3. 4 2
      core/src/main/java/org/springframework/security/authentication/AuthenticationObservationConvention.java
  4. 3 3
      core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java
  5. 4 3
      core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java
  6. 3 2
      core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java
  7. 3 2
      core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttributeEditor.java
  8. 8 7
      core/src/main/java/org/springframework/security/provisioning/InMemoryUserDetailsManager.java
  9. 4 3
      crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java
  10. 4 0
      etc/checkstyle/checkstyle-suppressions.xml
  11. 16 0
      etc/checkstyle/checkstyle.xml
  12. 4 2
      ldap/src/main/java/org/springframework/security/ldap/LdapEncoder.java
  13. 4 2
      ldap/src/main/java/org/springframework/security/ldap/authentication/LdapEncoder.java
  14. 5 4
      ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java
  15. 2 1
      ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java
  16. 3 2
      ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java
  17. 2 1
      ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java
  18. 3 2
      ldap/src/main/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulator.java
  19. 3 2
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java
  20. 3 2
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java
  21. 3 2
      taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java
  22. 3 1
      web/src/main/java/org/springframework/security/web/PortResolverImpl.java
  23. 2 1
      web/src/main/java/org/springframework/security/web/util/UrlUtils.java
  24. 4 3
      web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java

+ 3 - 1
cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java

@@ -18,6 +18,7 @@ package org.springframework.security.cas.userdetails;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.apereo.cas.client.validation.Assertion;
 
@@ -73,7 +74,8 @@ public final class GrantedAuthorityFromAssertionAttributesUserDetailsService
 	}
 
 	private SimpleGrantedAuthority createSimpleGrantedAuthority(Object o) {
-		return new SimpleGrantedAuthority(this.convertToUpperCase ? o.toString().toUpperCase() : o.toString());
+		return new SimpleGrantedAuthority(
+				this.convertToUpperCase ? o.toString().toUpperCase(Locale.ROOT) : o.toString());
 	}
 
 	/**

+ 3 - 2
config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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,6 +18,7 @@ package org.springframework.security.config.http;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import io.micrometer.observation.ObservationRegistry;
 import jakarta.servlet.ServletRequest;
@@ -313,7 +314,7 @@ class HttpConfigurationBuilder {
 
 	// Needed to account for placeholders
 	static String createPath(String path, boolean lowerCase) {
-		return lowerCase ? path.toLowerCase() : path;
+		return lowerCase ? path.toLowerCase(Locale.ENGLISH) : path;
 	}
 
 	BeanMetadataElement getSecurityContextHolderStrategyForAuthenticationFilters() {

+ 4 - 2
core/src/main/java/org/springframework/security/authentication/AuthenticationObservationConvention.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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.
@@ -16,6 +16,8 @@
 
 package org.springframework.security.authentication;
 
+import java.util.Locale;
+
 import io.micrometer.common.KeyValues;
 import io.micrometer.observation.Observation;
 import io.micrometer.observation.ObservationConvention;
@@ -53,7 +55,7 @@ public final class AuthenticationObservationConvention
 			if (authenticationType.endsWith("Authentication")) {
 				authenticationType = authenticationType.substring(0, authenticationType.lastIndexOf("Authentication"));
 			}
-			return "authenticate " + authenticationType.toLowerCase();
+			return "authenticate " + authenticationType.toLowerCase(Locale.ENGLISH);
 		}
 		return "authenticate";
 	}

+ 3 - 3
core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2024 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.
@@ -79,10 +79,10 @@ public class SimpleAttributes2GrantedAuthoritiesMapper
 	 */
 	private GrantedAuthority getGrantedAuthority(String attribute) {
 		if (isConvertAttributeToLowerCase()) {
-			attribute = attribute.toLowerCase(Locale.getDefault());
+			attribute = attribute.toLowerCase(Locale.ROOT);
 		}
 		else if (isConvertAttributeToUpperCase()) {
-			attribute = attribute.toUpperCase(Locale.getDefault());
+			attribute = attribute.toUpperCase(Locale.ROOT);
 		}
 		if (isAddPrefixIfAlreadyExisting() || !attribute.startsWith(getAttributePrefix())) {
 			return new SimpleGrantedAuthority(getAttributePrefix() + attribute);

+ 4 - 3
core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2024 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,6 +18,7 @@ package org.springframework.security.core.authority.mapping;
 
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Locale;
 import java.util.Set;
 
 import org.springframework.beans.factory.InitializingBean;
@@ -71,10 +72,10 @@ public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, In
 
 	private GrantedAuthority mapAuthority(String name) {
 		if (this.convertToUpperCase) {
-			name = name.toUpperCase();
+			name = name.toUpperCase(Locale.ROOT);
 		}
 		else if (this.convertToLowerCase) {
-			name = name.toLowerCase();
+			name = name.toLowerCase(Locale.ROOT);
 		}
 		if (this.prefix.length() > 0 && !name.startsWith(this.prefix)) {
 			name = this.prefix + name;

+ 3 - 2
core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2024 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,6 +18,7 @@ package org.springframework.security.core.userdetails;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -91,7 +92,7 @@ public class MapReactiveUserDetailsService implements ReactiveUserDetailsService
 	}
 
 	private String getKey(String username) {
-		return username.toLowerCase();
+		return username.toLowerCase(Locale.ROOT);
 	}
 
 }

+ 3 - 2
core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttributeEditor.java

@@ -19,6 +19,7 @@ package org.springframework.security.core.userdetails.memory;
 import java.beans.PropertyEditorSupport;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.springframework.util.StringUtils;
 
@@ -45,10 +46,10 @@ public class UserAttributeEditor extends PropertyEditorSupport {
 				userAttrib.setPassword(currentToken);
 			}
 			else {
-				if (currentToken.toLowerCase().equals("enabled")) {
+				if (currentToken.toLowerCase(Locale.ENGLISH).equals("enabled")) {
 					userAttrib.setEnabled(true);
 				}
-				else if (currentToken.toLowerCase().equals("disabled")) {
+				else if (currentToken.toLowerCase(Locale.ENGLISH).equals("disabled")) {
 					userAttrib.setEnabled(false);
 				}
 				else {

+ 8 - 7
core/src/main/java/org/springframework/security/provisioning/InMemoryUserDetailsManager.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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.provisioning;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 
@@ -96,23 +97,23 @@ public class InMemoryUserDetailsManager implements UserDetailsManager, UserDetai
 	@Override
 	public void createUser(UserDetails user) {
 		Assert.isTrue(!userExists(user.getUsername()), "user should not exist");
-		this.users.put(user.getUsername().toLowerCase(), new MutableUser(user));
+		this.users.put(user.getUsername().toLowerCase(Locale.ROOT), new MutableUser(user));
 	}
 
 	@Override
 	public void deleteUser(String username) {
-		this.users.remove(username.toLowerCase());
+		this.users.remove(username.toLowerCase(Locale.ROOT));
 	}
 
 	@Override
 	public void updateUser(UserDetails user) {
 		Assert.isTrue(userExists(user.getUsername()), "user should exist");
-		this.users.put(user.getUsername().toLowerCase(), new MutableUser(user));
+		this.users.put(user.getUsername().toLowerCase(Locale.ROOT), new MutableUser(user));
 	}
 
 	@Override
 	public boolean userExists(String username) {
-		return this.users.containsKey(username.toLowerCase());
+		return this.users.containsKey(username.toLowerCase(Locale.ROOT));
 	}
 
 	@Override
@@ -143,14 +144,14 @@ public class InMemoryUserDetailsManager implements UserDetailsManager, UserDetai
 	@Override
 	public UserDetails updatePassword(UserDetails user, String newPassword) {
 		String username = user.getUsername();
-		MutableUserDetails mutableUser = this.users.get(username.toLowerCase());
+		MutableUserDetails mutableUser = this.users.get(username.toLowerCase(Locale.ROOT));
 		mutableUser.setPassword(newPassword);
 		return mutableUser;
 	}
 
 	@Override
 	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-		UserDetails user = this.users.get(username.toLowerCase());
+		UserDetails user = this.users.get(username.toLowerCase(Locale.ROOT));
 		if (user == null) {
 			throw new UsernameNotFoundException(username);
 		}

+ 4 - 3
crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2024 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,6 +18,7 @@ package org.springframework.security.crypto.password;
 
 import java.security.MessageDigest;
 import java.util.Base64;
+import java.util.Locale;
 
 import org.springframework.security.crypto.codec.Utf8;
 import org.springframework.security.crypto.keygen.BytesKeyGenerator;
@@ -50,11 +51,11 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
 
 	private static final String SSHA_PREFIX = "{SSHA}";
 
-	private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase();
+	private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase(Locale.ENGLISH);
 
 	private static final String SHA_PREFIX = "{SHA}";
 
-	private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase();
+	private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase(Locale.ENGLISH);
 
 	private BytesKeyGenerator saltGenerator;
 

+ 4 - 0
etc/checkstyle/checkstyle-suppressions.xml

@@ -40,4 +40,8 @@
 
 	<!-- Lambdas that we can't replace with a method reference because a closure is required -->
 	<suppress files="BearerTokenAuthenticationFilter\.java" checks="SpringLambda"/>
+
+	<!-- Ignore String.toUpperCase() and String.toLowerCase() checks in tests -->
+	<suppress files="[\\/]src[\\/]test[\\/]" checks="RegexpSinglelineJava" id="toLowerCaseWithoutLocale"/>
+	<suppress files="[\\/]src[\\/]test[\\/]" checks="RegexpSinglelineJava" id="toUpperCaseWithoutLocale"/>
 </suppressions>

+ 16 - 0
etc/checkstyle/checkstyle.xml

@@ -30,5 +30,21 @@
 			<property name="message" value="Please use assertThatExceptionOfType." />
 			<property name="ignoreComments" value="true" />
 		</module>
+		<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
+			<property name="id" value="toLowerCaseWithoutLocale"/>
+			<property name="format" value="\.toLowerCase\(\)"/>
+			<property name="maximum" value="0"/>
+			<property name="message"
+					  value="String.toLowerCase() should be String.toLowerCase(Locale.ROOT) or String.toLowerCase(Locale.ENGLISH)"/>
+			<property name="ignoreComments" value="true"/>
+		</module>
+		<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
+			<property name="id" value="toUpperCaseWithoutLocale"/>
+			<property name="format" value="\.toUpperCase\(\)"/>
+			<property name="maximum" value="0"/>
+			<property name="message"
+					  value="String.toUpperCase() should be String.toUpperCase(Locale.ROOT) or String.toUpperCase(Locale.ENGLISH)"/>
+			<property name="ignoreComments" value="true"/>
+		</module>
 	</module>
 </module>

+ 4 - 2
ldap/src/main/java/org/springframework/security/ldap/LdapEncoder.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2010 the original author or authors.
+ * Copyright 2005-2024 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.
@@ -16,6 +16,8 @@
 
 package org.springframework.security.ldap;
 
+import java.util.Locale;
+
 import org.springframework.ldap.BadLdapGrammarException;
 
 /**
@@ -72,7 +74,7 @@ final class LdapEncoder {
 	}
 
 	protected static String toTwoCharHex(char c) {
-		String raw = Integer.toHexString(c).toUpperCase();
+		String raw = Integer.toHexString(c).toUpperCase(Locale.ENGLISH);
 		return (raw.length() > 1) ? raw : "0" + raw;
 	}
 

+ 4 - 2
ldap/src/main/java/org/springframework/security/ldap/authentication/LdapEncoder.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2010 the original author or authors.
+ * Copyright 2005-2024 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.
@@ -16,6 +16,8 @@
 
 package org.springframework.security.ldap.authentication;
 
+import java.util.Locale;
+
 import org.springframework.ldap.BadLdapGrammarException;
 
 /**
@@ -72,7 +74,7 @@ final class LdapEncoder {
 	}
 
 	protected static String toTwoCharHex(char c) {
-		String raw = Integer.toHexString(c).toUpperCase();
+		String raw = Integer.toHexString(c).toUpperCase(Locale.ENGLISH);
 		return (raw.length() > 1) ? raw : "0" + raw;
 	}
 

+ 5 - 4
ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java

@@ -20,6 +20,7 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.Locale;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -142,9 +143,9 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
 	 */
 	public ActiveDirectoryLdapAuthenticationProvider(String domain, String url, String rootDn) {
 		Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty");
-		this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null;
+		this.domain = StringUtils.hasText(domain) ? domain.toLowerCase(Locale.ROOT) : null;
 		this.url = url;
-		this.rootDn = StringUtils.hasText(rootDn) ? rootDn.toLowerCase() : null;
+		this.rootDn = StringUtils.hasText(rootDn) ? rootDn.toLowerCase(Locale.ROOT) : null;
 	}
 
 	/**
@@ -153,7 +154,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
 	 */
 	public ActiveDirectoryLdapAuthenticationProvider(String domain, String url) {
 		Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty");
-		this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null;
+		this.domain = StringUtils.hasText(domain) ? domain.toLowerCase(Locale.ROOT) : null;
 		this.url = url;
 		this.rootDn = (this.domain != null) ? rootDnFromDomain(this.domain) : null;
 	}
@@ -336,7 +337,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
 	}
 
 	String createBindPrincipal(String username) {
-		if (this.domain == null || username.toLowerCase().endsWith(this.domain)) {
+		if (this.domain == null || username.toLowerCase(Locale.ROOT).endsWith(this.domain)) {
 			return username;
 		}
 		return username + "@" + this.domain;

+ 2 - 1
ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java

@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Function;
@@ -179,7 +180,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
 				return null;
 			}
 			if (this.convertToUpperCase) {
-				role = role.toUpperCase();
+				role = role.toUpperCase(Locale.ROOT);
 			}
 			return new SimpleGrantedAuthority(this.rolePrefix + role);
 		};

+ 3 - 2
ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java

@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Locale;
 
 import javax.naming.Context;
 import javax.naming.NameNotFoundException;
@@ -124,7 +125,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
 		NamingEnumeration<?> ne = roleAttr.getAll();
 		Object group = ne.next();
 		String role = group.toString();
-		return new SimpleGrantedAuthority(this.rolePrefix + role.toUpperCase());
+		return new SimpleGrantedAuthority(this.rolePrefix + role.toUpperCase(Locale.ROOT));
 	};
 
 	private String[] attributesToRetrieve;
@@ -287,7 +288,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
 	 */
 	protected DistinguishedName buildGroupDn(String group) {
 		DistinguishedName dn = new DistinguishedName(this.groupSearchBase);
-		dn.add(this.groupRoleAttributeName, group.toLowerCase());
+		dn.add(this.groupRoleAttributeName, group.toLowerCase(Locale.ROOT));
 		return dn;
 	}
 

+ 2 - 1
ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java

@@ -17,6 +17,7 @@
 package org.springframework.security.ldap.userdetails;
 
 import java.util.Collection;
+import java.util.Locale;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -127,7 +128,7 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper {
 	protected GrantedAuthority createAuthority(Object role) {
 		if (role instanceof String) {
 			if (this.convertToUpperCase) {
-				role = ((String) role).toUpperCase();
+				role = ((String) role).toUpperCase(Locale.ROOT);
 			}
 			return new SimpleGrantedAuthority(this.rolePrefix + role);
 		}

+ 3 - 2
ldap/src/main/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulator.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2024 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,6 +18,7 @@ package org.springframework.security.ldap.userdetails;
 
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
@@ -193,7 +194,7 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula
 			}
 			for (String role : roles) {
 				if (isConvertToUpperCase()) {
-					role = role.toUpperCase();
+					role = role.toUpperCase(Locale.ROOT);
 				}
 				role = getRolePrefix() + role;
 				// if the group already exist, we will not search for it's parents again.

+ 3 - 2
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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,6 +18,7 @@ package org.springframework.security.oauth2.client.web.reactive.function.client;
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Consumer;
@@ -539,7 +540,7 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
 			// @formatter:off
 			return Stream.of(wwwAuthenticateHeader)
 					.filter((header) -> StringUtils.hasLength(header))
-					.filter((header) -> header.toLowerCase().startsWith("bearer"))
+					.filter((header) -> header.toLowerCase(Locale.ENGLISH).startsWith("bearer"))
 					.map((header) -> header.substring("bearer".length()))
 					.map((header) -> header.split(","))
 					.flatMap(Stream::of)

+ 3 - 2
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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,6 +18,7 @@ package org.springframework.security.oauth2.client.web.reactive.function.client;
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
@@ -654,7 +655,7 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement
 		private Map<String, String> parseAuthParameters(String wwwAuthenticateHeader) {
 			// @formatter:off
 			return Stream.of(wwwAuthenticateHeader).filter((header) -> StringUtils.hasLength(header))
-					.filter((header) -> header.toLowerCase().startsWith("bearer"))
+					.filter((header) -> header.toLowerCase(Locale.ENGLISH).startsWith("bearer"))
 					.map((header) -> header.substring("bearer".length()))
 					.map((header) -> header.split(","))
 					.flatMap(Stream::of)

+ 3 - 2
taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2022 the original author or authors.
+ * Copyright 2004-2024 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,6 +17,7 @@
 package org.springframework.security.taglibs.authz;
 
 import java.io.IOException;
+import java.util.Locale;
 import java.util.Map;
 
 import jakarta.servlet.ServletContext;
@@ -169,7 +170,7 @@ public abstract class AbstractAuthorizeTag {
 	}
 
 	public void setMethod(String method) {
-		this.method = (method != null) ? method.toUpperCase() : null;
+		this.method = (method != null) ? method.toUpperCase(Locale.ENGLISH) : null;
 	}
 
 	private SecurityContext getContext() {

+ 3 - 1
web/src/main/java/org/springframework/security/web/PortResolverImpl.java

@@ -16,6 +16,8 @@
 
 package org.springframework.security.web;
 
+import java.util.Locale;
+
 import jakarta.servlet.ServletRequest;
 
 import org.springframework.util.Assert;
@@ -45,7 +47,7 @@ public class PortResolverImpl implements PortResolver {
 	@Override
 	public int getServerPort(ServletRequest request) {
 		int serverPort = request.getServerPort();
-		String scheme = request.getScheme().toLowerCase();
+		String scheme = request.getScheme().toLowerCase(Locale.ENGLISH);
 		Integer mappedPort = getMappedPort(serverPort, scheme);
 		return (mappedPort != null) ? mappedPort : serverPort;
 	}

+ 2 - 1
web/src/main/java/org/springframework/security/web/util/UrlUtils.java

@@ -16,6 +16,7 @@
 
 package org.springframework.security.web.util;
 
+import java.util.Locale;
 import java.util.regex.Pattern;
 
 import jakarta.servlet.http.HttpServletRequest;
@@ -49,7 +50,7 @@ public final class UrlUtils {
 	 */
 	public static String buildFullRequestUrl(String scheme, String serverName, int serverPort, String requestURI,
 			String queryString) {
-		scheme = scheme.toLowerCase();
+		scheme = scheme.toLowerCase(Locale.ENGLISH);
 		StringBuilder url = new StringBuilder();
 		url.append(scheme).append("://").append(serverName);
 		// Only add port if not default

+ 4 - 3
web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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,6 +17,7 @@
 package org.springframework.security.web.util.matcher;
 
 import java.util.Collections;
+import java.util.Locale;
 import java.util.Map;
 
 import jakarta.servlet.http.HttpServletRequest;
@@ -303,7 +304,7 @@ public final class AntPathRequestMatcher implements RequestMatcher, RequestVaria
 
 		private SubpathMatcher(String subpath, boolean caseSensitive) {
 			Assert.isTrue(!subpath.contains("*"), "subpath cannot contain \"*\"");
-			this.subpath = caseSensitive ? subpath : subpath.toLowerCase();
+			this.subpath = caseSensitive ? subpath : subpath.toLowerCase(Locale.ROOT);
 			this.length = subpath.length();
 			this.caseSensitive = caseSensitive;
 		}
@@ -311,7 +312,7 @@ public final class AntPathRequestMatcher implements RequestMatcher, RequestVaria
 		@Override
 		public boolean matches(String path) {
 			if (!this.caseSensitive) {
-				path = path.toLowerCase();
+				path = path.toLowerCase(Locale.ROOT);
 			}
 			return path.startsWith(this.subpath) && (path.length() == this.length || path.charAt(this.length) == '/');
 		}