diff --git a/src/main/java/io/lettuce/core/RedisURI.java b/src/main/java/io/lettuce/core/RedisURI.java index 521aa8d4ae..d8812f68e3 100644 --- a/src/main/java/io/lettuce/core/RedisURI.java +++ b/src/main/java/io/lettuce/core/RedisURI.java @@ -760,8 +760,8 @@ private static RedisURI buildRedisUriFromUri(URI uri) { String userInfo = uri.getUserInfo(); - if (isEmpty(userInfo) && isNotEmpty(uri.getAuthority()) && uri.getAuthority().indexOf('@') > 0) { - userInfo = uri.getAuthority().substring(0, uri.getAuthority().indexOf('@')); + if (isEmpty(userInfo) && isNotEmpty(uri.getAuthority()) && uri.getAuthority().lastIndexOf('@') > 0) { + userInfo = uri.getAuthority().substring(0, uri.getAuthority().lastIndexOf('@')); } if (isNotEmpty(userInfo)) { @@ -1121,7 +1121,7 @@ private static Builder configureStandalone(URI uri) { if (isNotEmpty(uri.getAuthority())) { String authority = uri.getAuthority(); if (authority.indexOf('@') > -1) { - authority = authority.substring(authority.indexOf('@') + 1); + authority = authority.substring(authority.lastIndexOf('@') + 1); } builder = Builder.redis(authority); @@ -1158,7 +1158,7 @@ private static RedisURI.Builder configureSentinel(URI uri) { if (builder == null && isNotEmpty(uri.getAuthority())) { String authority = uri.getAuthority(); if (authority.indexOf('@') > -1) { - authority = authority.substring(authority.indexOf('@') + 1); + authority = authority.substring(authority.lastIndexOf('@') + 1); } String[] hosts = authority.split(","); diff --git a/src/test/java/io/lettuce/core/RedisURIUnitTests.java b/src/test/java/io/lettuce/core/RedisURIUnitTests.java index c22d266c31..62f9d0fea1 100644 --- a/src/test/java/io/lettuce/core/RedisURIUnitTests.java +++ b/src/test/java/io/lettuce/core/RedisURIUnitTests.java @@ -17,6 +17,9 @@ import static org.assertj.core.api.Assertions.*; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.LinkedHashMap; import java.util.Map; @@ -189,6 +192,24 @@ void socketAltUriTest() { assertThat(redisURI).hasToString("redis-socket:///var/tmp/other-socket?database=2"); } + @Test + void escapeCharacterParsingTest() throws UnsupportedEncodingException { + String password = "abc@#d"; + String translatedPassword = URLEncoder.encode(password, StandardCharsets.UTF_8.name()); + + // redis sentinel + String uri = "redis-sentinel://"+translatedPassword+"@h1:1234,h2:1234,h3:1234/0?sentinelMasterId=masterId"; + RedisURI redisURI = RedisURI.create(uri); + assertThat(redisURI.getSentinels().get(0).getHost()).isEqualTo("h1"); + assertThat(String.valueOf(redisURI.getCredentialsProvider().resolveCredentials().block().getPassword())).isEqualTo(password); + + // redis standalone + uri = "redis://"+translatedPassword+"@h1:1234/0"; + redisURI = RedisURI.create(uri); + assertThat(redisURI.getHost()).isEqualTo("h1"); + assertThat(String.valueOf(redisURI.getCredentialsProvider().resolveCredentials().block().getPassword())).isEqualTo(password); + } + @Test void timeoutParsingTest() {