Remove dependency on commons-codec by using java.util.Base64
Closes gh-11318
This commit is contained in:
parent
d1cb236df5
commit
f3c96fa9cd
|
@ -105,12 +105,6 @@ updateDependenciesSettings {
|
|||
alphaBetaVersions()
|
||||
snapshotVersions()
|
||||
addRule { components ->
|
||||
components.withModule("commons-codec:commons-codec") { selection ->
|
||||
ModuleComponentIdentifier candidate = selection.getCandidate();
|
||||
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
|
||||
selection.reject("commons-codec updates break saml tests");
|
||||
}
|
||||
}
|
||||
components.withModule("org.python:jython") { selection ->
|
||||
ModuleComponentIdentifier candidate = selection.getCandidate();
|
||||
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
|
||||
|
|
|
@ -23,7 +23,6 @@ dependencies {
|
|||
api "com.squareup.okhttp3:mockwebserver:3.14.9"
|
||||
api "com.squareup.okhttp3:okhttp:3.14.9"
|
||||
api "com.unboundid:unboundid-ldapsdk:4.0.14"
|
||||
api "commons-codec:commons-codec:1.15"
|
||||
api "commons-collections:commons-collections:3.2.2"
|
||||
api "io.mockk:mockk:1.12.4"
|
||||
api "jakarta.annotation:jakarta.annotation-api:2.1.0"
|
||||
|
|
|
@ -15,7 +15,6 @@ dependencies {
|
|||
optional 'jakarta.servlet:jakarta.servlet-api'
|
||||
|
||||
testImplementation project(path: ':spring-security-core', configuration: 'tests')
|
||||
testImplementation 'commons-codec:commons-codec'
|
||||
testImplementation "org.assertj:assertj-core"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
||||
|
|
|
@ -18,13 +18,13 @@ package org.springframework.security.saml2.provider.service.web;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.function.Function;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterOutputStream;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.codec.CodecPolicy;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
|
@ -47,7 +47,11 @@ import org.springframework.util.Assert;
|
|||
*/
|
||||
public final class Saml2AuthenticationTokenConverter implements AuthenticationConverter {
|
||||
|
||||
private static Base64 BASE64 = new Base64(0, new byte[] { '\n' }, false, CodecPolicy.STRICT);
|
||||
// MimeDecoder allows extra line-breaks as well as other non-alphabet values.
|
||||
// This matches the behaviour of the commons-codec decoder.
|
||||
private static final Base64.Decoder BASE64 = Base64.getMimeDecoder();
|
||||
|
||||
private static final Base64Checker BASE_64_CHECKER = new Base64Checker();
|
||||
|
||||
private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
|
||||
|
||||
|
@ -110,6 +114,7 @@ public final class Saml2AuthenticationTokenConverter implements AuthenticationCo
|
|||
|
||||
private byte[] samlDecode(String base64EncodedPayload) {
|
||||
try {
|
||||
BASE_64_CHECKER.checkAcceptable(base64EncodedPayload);
|
||||
return BASE64.decode(base64EncodedPayload);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
@ -132,4 +137,58 @@ public final class Saml2AuthenticationTokenConverter implements AuthenticationCo
|
|||
}
|
||||
}
|
||||
|
||||
static class Base64Checker {
|
||||
|
||||
private static final int[] values = genValueMapping();
|
||||
|
||||
Base64Checker() {
|
||||
|
||||
}
|
||||
|
||||
private static int[] genValueMapping() {
|
||||
byte[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
.getBytes(StandardCharsets.ISO_8859_1);
|
||||
|
||||
int[] values = new int[256];
|
||||
Arrays.fill(values, -1);
|
||||
for (int i = 0; i < alphabet.length; i++) {
|
||||
values[alphabet[i] & 0xff] = i;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
boolean isAcceptable(String s) {
|
||||
int goodChars = 0;
|
||||
int lastGoodCharVal = -1;
|
||||
|
||||
// count number of characters from Base64 alphabet
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
int val = values[0xff & s.charAt(i)];
|
||||
if (val != -1) {
|
||||
lastGoodCharVal = val;
|
||||
goodChars++;
|
||||
}
|
||||
}
|
||||
|
||||
// in cases of an incomplete final chunk, ensure the unused bits are zero
|
||||
switch (goodChars % 4) {
|
||||
case 0:
|
||||
return true;
|
||||
case 2:
|
||||
return (lastGoodCharVal & 0b1111) == 0;
|
||||
case 3:
|
||||
return (lastGoodCharVal & 0b11) == 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void checkAcceptable(String ins) {
|
||||
if (!isAcceptable(ins)) {
|
||||
throw new IllegalArgumentException("Unaccepted Encoding");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ dependencies {
|
|||
provided 'jakarta.servlet:jakarta.servlet-api'
|
||||
|
||||
testImplementation project(path: ':spring-security-core', configuration: 'tests')
|
||||
testImplementation 'commons-codec:commons-codec'
|
||||
testImplementation 'io.projectreactor:reactor-test'
|
||||
testImplementation 'jakarta.xml.bind:jakarta.xml.bind-api'
|
||||
testImplementation 'org.hamcrest:hamcrest'
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.
|
||||
* 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.test.web;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
public final class CodecTestUtils {
|
||||
|
||||
private CodecTestUtils() {
|
||||
}
|
||||
|
||||
public static String encodeBase64(String unencoded) {
|
||||
return Base64.getEncoder().encodeToString(unencoded.getBytes());
|
||||
}
|
||||
|
||||
public static String encodeBase64(byte[] unencoded) {
|
||||
return Base64.getEncoder().encodeToString(unencoded);
|
||||
}
|
||||
|
||||
public static String decodeBase64(String encoded) {
|
||||
return new String(Base64.getDecoder().decode(encoded));
|
||||
}
|
||||
|
||||
public static boolean isBase64(byte[] arrayOctet) {
|
||||
try {
|
||||
Base64.getMimeDecoder().decode(arrayOctet);
|
||||
return true;
|
||||
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String md5Hex(String data) {
|
||||
return DigestUtils.md5DigestAsHex(data.getBytes());
|
||||
}
|
||||
|
||||
}
|
|
@ -19,8 +19,6 @@ package org.springframework.security.web.authentication.rememberme;
|
|||
import java.util.Date;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -33,6 +31,7 @@ import org.springframework.security.core.userdetails.User;
|
|||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.test.web.CodecTestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -76,7 +75,7 @@ public class TokenBasedRememberMeServicesTests {
|
|||
}
|
||||
|
||||
private long determineExpiryTimeFromBased64EncodedToken(String validToken) {
|
||||
String cookieAsPlainText = new String(Base64.decodeBase64(validToken.getBytes()));
|
||||
String cookieAsPlainText = CodecTestUtils.decodeBase64(validToken);
|
||||
String[] cookieTokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, ":");
|
||||
if (cookieTokens.length == 3) {
|
||||
try {
|
||||
|
@ -92,9 +91,9 @@ public class TokenBasedRememberMeServicesTests {
|
|||
// format is:
|
||||
// username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" +
|
||||
// password + ":" + key)
|
||||
String signatureValue = DigestUtils.md5Hex(username + ":" + expiryTime + ":" + password + ":" + key);
|
||||
String signatureValue = CodecTestUtils.md5Hex(username + ":" + expiryTime + ":" + password + ":" + key);
|
||||
String tokenValue = username + ":" + expiryTime + ":" + signatureValue;
|
||||
return new String(Base64.encodeBase64(tokenValue.getBytes()));
|
||||
return CodecTestUtils.encodeBase64(tokenValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -134,7 +133,7 @@ public class TokenBasedRememberMeServicesTests {
|
|||
@Test
|
||||
public void autoLoginReturnsNullAndClearsCookieIfMissingThreeTokensInCookieValue() {
|
||||
Cookie cookie = new Cookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
new String(Base64.encodeBase64("x".getBytes())));
|
||||
CodecTestUtils.encodeBase64("x"));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(cookie);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -175,7 +174,7 @@ public class TokenBasedRememberMeServicesTests {
|
|||
@Test
|
||||
public void autoLoginClearsCookieIfTokenDoesNotContainANumberInCookieValue() {
|
||||
Cookie cookie = new Cookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
new String(Base64.encodeBase64("username:NOT_A_NUMBER:signature".getBytes())));
|
||||
CodecTestUtils.encodeBase64("username:NOT_A_NUMBER:signature"));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(cookie);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -275,7 +274,7 @@ public class TokenBasedRememberMeServicesTests {
|
|||
assertThat(Long.parseLong(expiryTime) > expectedExpiryTime - 10000).isTrue();
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.getMaxAge()).isEqualTo(this.services.getTokenValiditySeconds());
|
||||
assertThat(Base64.isArrayByteBase64(cookie.getValue().getBytes())).isTrue();
|
||||
assertThat(CodecTestUtils.isBase64(cookie.getValue().getBytes())).isTrue();
|
||||
assertThat(new Date().before(new Date(determineExpiryTimeFromBased64EncodedToken(cookie.getValue())))).isTrue();
|
||||
}
|
||||
|
||||
|
@ -289,7 +288,7 @@ public class TokenBasedRememberMeServicesTests {
|
|||
Cookie cookie = response.getCookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.getMaxAge()).isEqualTo(this.services.getTokenValiditySeconds());
|
||||
assertThat(Base64.isArrayByteBase64(cookie.getValue().getBytes())).isTrue();
|
||||
assertThat(CodecTestUtils.isBase64(cookie.getValue().getBytes())).isTrue();
|
||||
assertThat(new Date().before(new Date(determineExpiryTimeFromBased64EncodedToken(cookie.getValue())))).isTrue();
|
||||
}
|
||||
|
||||
|
@ -315,7 +314,7 @@ public class TokenBasedRememberMeServicesTests {
|
|||
assertThat(determineExpiryTimeFromBased64EncodedToken(cookie.getValue())
|
||||
- System.currentTimeMillis() > AbstractRememberMeServices.TWO_WEEKS_S - 50).isTrue();
|
||||
assertThat(cookie.getMaxAge()).isEqualTo(-1);
|
||||
assertThat(Base64.isArrayByteBase64(cookie.getValue().getBytes())).isTrue();
|
||||
assertThat(CodecTestUtils.isBase64(cookie.getValue().getBytes())).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.security.web.authentication.www;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
@ -28,6 +27,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
|||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.test.web.CodecTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
@ -56,7 +56,7 @@ public class BasicAuthenticationConverterTests {
|
|||
public void testNormalOperation() {
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
UsernamePasswordAuthenticationToken authentication = this.converter.convert(request);
|
||||
verify(this.authenticationDetailsSource).buildDetails(any());
|
||||
assertThat(authentication).isNotNull();
|
||||
|
@ -67,7 +67,7 @@ public class BasicAuthenticationConverterTests {
|
|||
public void requestWhenAuthorizationSchemeInMixedCaseThenAuthenticates() {
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "BaSiC " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "BaSiC " + CodecTestUtils.encodeBase64(token));
|
||||
UsernamePasswordAuthenticationToken authentication = this.converter.convert(request);
|
||||
verify(this.authenticationDetailsSource).buildDetails(any());
|
||||
assertThat(authentication).isNotNull();
|
||||
|
@ -87,7 +87,7 @@ public class BasicAuthenticationConverterTests {
|
|||
public void testWhenInvalidBasicAuthorizationTokenThenError() {
|
||||
String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> this.converter.convert(request));
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class BasicAuthenticationConverterTests {
|
|||
public void convertWhenEmptyPassword() {
|
||||
String token = "rod:";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
UsernamePasswordAuthenticationToken authentication = this.converter.convert(request);
|
||||
verify(this.authenticationDetailsSource).buildDetails(any());
|
||||
assertThat(authentication).isNotNull();
|
||||
|
|
|
@ -22,7 +22,6 @@ import jakarta.servlet.FilterChain;
|
|||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -38,6 +37,7 @@ import org.springframework.security.core.Authentication;
|
|||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.test.web.CodecTestUtils;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
@ -104,7 +104,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void testInvalidBasicAuthorizationTokenIsIgnored() throws Exception {
|
||||
String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -134,7 +134,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void testNormalOperation() throws Exception {
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
// Test
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
|
||||
|
@ -150,7 +150,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void doFilterWhenSchemeLowercaseThenCaseInsensitveMatchWorks() throws Exception {
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
// Test
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
|
||||
|
@ -165,7 +165,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void doFilterWhenSchemeMixedCaseThenCaseInsensitiveMatchWorks() throws Exception {
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "BaSiC " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "BaSiC " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
@ -200,7 +200,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws Exception {
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
final MockHttpServletResponse response1 = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
@ -212,7 +212,7 @@ public class BasicAuthenticationFilterTests {
|
|||
// NOW PERFORM FAILED AUTHENTICATION
|
||||
token = "otherUser:WRONG_PASSWORD";
|
||||
request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
final MockHttpServletResponse response2 = new MockHttpServletResponse();
|
||||
chain = mock(FilterChain.class);
|
||||
this.filter.doFilter(request, response2, chain);
|
||||
|
@ -228,7 +228,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void testWrongPasswordContinuesFilterChainIfIgnoreFailureIsTrue() throws Exception {
|
||||
String token = "rod:WRONG_PASSWORD";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
this.filter = new BasicAuthenticationFilter(this.manager);
|
||||
|
@ -244,7 +244,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void testWrongPasswordReturnsForbiddenIfIgnoreFailureIsFalse() throws Exception {
|
||||
String token = "rod:WRONG_PASSWORD";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
assertThat(this.filter.isIgnoreFailure()).isFalse();
|
||||
|
@ -262,7 +262,7 @@ public class BasicAuthenticationFilterTests {
|
|||
public void skippedOnErrorDispatch() throws Exception {
|
||||
String token = "bad:credentials";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE, "/error");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -286,7 +286,7 @@ public class BasicAuthenticationFilterTests {
|
|||
String token = "rod:äöü";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization",
|
||||
"Basic " + new String(Base64.encodeBase64(token.getBytes(StandardCharsets.UTF_8))));
|
||||
"Basic " + CodecTestUtils.encodeBase64(token.getBytes(StandardCharsets.UTF_8)));
|
||||
request.setServletPath("/some_file.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
// Test
|
||||
|
@ -315,7 +315,7 @@ public class BasicAuthenticationFilterTests {
|
|||
String token = "rod:äöü";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization",
|
||||
"Basic " + new String(Base64.encodeBase64(token.getBytes(StandardCharsets.ISO_8859_1))));
|
||||
"Basic " + CodecTestUtils.encodeBase64(token.getBytes(StandardCharsets.ISO_8859_1)));
|
||||
request.setServletPath("/some_file.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
// Test
|
||||
|
@ -344,7 +344,7 @@ public class BasicAuthenticationFilterTests {
|
|||
String token = "rod:äöü";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization",
|
||||
"Basic " + new String(Base64.encodeBase64(token.getBytes(StandardCharsets.UTF_8))));
|
||||
"Basic " + CodecTestUtils.encodeBase64(token.getBytes(StandardCharsets.UTF_8)));
|
||||
request.setServletPath("/some_file.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
// Test
|
||||
|
@ -377,7 +377,7 @@ public class BasicAuthenticationFilterTests {
|
|||
this.filter.setSecurityContextRepository(securityContextRepository);
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token));
|
||||
request.setServletPath("/some_file.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
// Test
|
||||
|
|
|
@ -18,13 +18,12 @@ package org.springframework.security.web.authentication.www;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.test.web.CodecTestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -41,11 +40,11 @@ public class DigestAuthenticationEntryPointTests {
|
|||
// Check the nonce seems to be generated correctly
|
||||
// format of nonce is:
|
||||
// base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
|
||||
assertThat(Base64.isArrayByteBase64(nonce.getBytes())).isTrue();
|
||||
String decodedNonce = new String(Base64.decodeBase64(nonce.getBytes()));
|
||||
assertThat(CodecTestUtils.isBase64(nonce.getBytes())).isTrue();
|
||||
String decodedNonce = CodecTestUtils.decodeBase64(nonce);
|
||||
String[] nonceTokens = StringUtils.delimitedListToStringArray(decodedNonce, ":");
|
||||
assertThat(nonceTokens).hasSize(2);
|
||||
String expectedNonceSignature = DigestUtils.md5Hex(nonceTokens[0] + ":" + "key");
|
||||
String expectedNonceSignature = CodecTestUtils.md5Hex(nonceTokens[0] + ":" + "key");
|
||||
assertThat(nonceTokens[1]).isEqualTo(expectedNonceSignature);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,6 @@ import jakarta.servlet.Filter;
|
|||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -40,6 +38,7 @@ import org.springframework.security.core.userdetails.User;
|
|||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.cache.NullUserCache;
|
||||
import org.springframework.security.test.web.CodecTestUtils;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
@ -105,9 +104,9 @@ public class DigestAuthenticationFilterTests {
|
|||
|
||||
private static String generateNonce(int validitySeconds, String key) {
|
||||
long expiryTime = System.currentTimeMillis() + (validitySeconds * 1000);
|
||||
String signatureValue = DigestUtils.md5Hex(expiryTime + ":" + key);
|
||||
String signatureValue = CodecTestUtils.md5Hex(expiryTime + ":" + key);
|
||||
String nonceValue = expiryTime + ":" + signatureValue;
|
||||
return new String(Base64.encodeBase64(nonceValue.getBytes()));
|
||||
return CodecTestUtils.encodeBase64(nonceValue);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
@ -182,7 +181,7 @@ public class DigestAuthenticationFilterTests {
|
|||
@Test
|
||||
public void testInvalidDigestAuthorizationTokenGeneratesError() throws Exception {
|
||||
String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON";
|
||||
this.request.addHeader("Authorization", "Digest " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
this.request.addHeader("Authorization", "Digest " + CodecTestUtils.encodeBase64(token));
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(this.filter, this.request, false);
|
||||
assertThat(response.getStatus()).isEqualTo(401);
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
|
||||
|
@ -210,7 +209,7 @@ public class DigestAuthenticationFilterTests {
|
|||
|
||||
@Test
|
||||
public void testNonceWithIncorrectSignatureForNumericFieldReturnsForbidden() throws Exception {
|
||||
String nonce = new String(Base64.encodeBase64("123456:incorrectStringPassword".getBytes()));
|
||||
String nonce = CodecTestUtils.encodeBase64("123456:incorrectStringPassword");
|
||||
String responseDigest = DigestAuthUtils.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI,
|
||||
QOP, nonce, NC, CNONCE);
|
||||
this.request.addHeader("Authorization",
|
||||
|
@ -222,7 +221,7 @@ public class DigestAuthenticationFilterTests {
|
|||
|
||||
@Test
|
||||
public void testNonceWithNonNumericFirstElementReturnsForbidden() throws Exception {
|
||||
String nonce = new String(Base64.encodeBase64("hello:ignoredSecondElement".getBytes()));
|
||||
String nonce = CodecTestUtils.encodeBase64("hello:ignoredSecondElement");
|
||||
String responseDigest = DigestAuthUtils.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI,
|
||||
QOP, nonce, NC, CNONCE);
|
||||
this.request.addHeader("Authorization",
|
||||
|
@ -234,7 +233,7 @@ public class DigestAuthenticationFilterTests {
|
|||
|
||||
@Test
|
||||
public void testNonceWithoutTwoColonSeparatedElementsReturnsForbidden() throws Exception {
|
||||
String nonce = new String(Base64.encodeBase64("a base 64 string without a colon".getBytes()));
|
||||
String nonce = CodecTestUtils.encodeBase64("a base 64 string without a colon");
|
||||
String responseDigest = DigestAuthUtils.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI,
|
||||
QOP, nonce, NC, CNONCE);
|
||||
this.request.addHeader("Authorization",
|
||||
|
|
Loading…
Reference in New Issue