From fa245c7a1a9bd68fa76e7033a7ae8595b269fdaa Mon Sep 17 00:00:00 2001 From: huazhongming Date: Wed, 3 Nov 2021 10:59:39 +0800 Subject: [PATCH] According to rfc3986, revise the logic of changing the authority in the URL (#9170) --- .../java/org/apache/dubbo/common/URL.java | 76 ++++++++++++++----- .../java/org/apache/dubbo/common/URLTest.java | 76 ++++++++++++++----- .../java/com/alibaba/dubbo/common/URL.java | 5 +- .../curator5/Curator5ZookeeperClient.java | 6 +- .../curator/CuratorZookeeperClient.java | 6 +- 5 files changed, 122 insertions(+), 47 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java index ea88a3e214..dea541cf5e 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java @@ -187,7 +187,7 @@ class URL implements Serializable { String path, Map parameters) { if (StringUtils.isEmpty(username) - && StringUtils.isNotEmpty(password)) { + && StringUtils.isNotEmpty(password)) { throw new IllegalArgumentException("Invalid url, password without username!"); } @@ -197,15 +197,15 @@ class URL implements Serializable { } protected URL(String protocol, - String username, - String password, - String host, - int port, - String path, - Map parameters, - boolean modifiable) { + String username, + String password, + String host, + int port, + String path, + Map parameters, + boolean modifiable) { if (StringUtils.isEmpty(username) - && StringUtils.isNotEmpty(password)) { + && StringUtils.isNotEmpty(password)) { throw new IllegalArgumentException("Invalid url, password without username!"); } @@ -215,7 +215,7 @@ class URL implements Serializable { } public static URL cacheableValueOf(String url) { - URL cachedURL = cachedURLs.get(url); + URL cachedURL = cachedURLs.get(url); if (cachedURL != null) { return cachedURL; } @@ -292,7 +292,7 @@ class URL implements Serializable { } } return newMap.isEmpty() ? new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), (Map) null, url.getAttributes()) - : new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap, url.getAttributes()); + : new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap, url.getAttributes()); } public static String encode(String value) { @@ -364,13 +364,53 @@ class URL implements Serializable { return returnURL(newURLAddress); } + /** + * refer to https://datatracker.ietf.org/doc/html/rfc3986 + * + * @return authority + */ public String getAuthority() { - if (StringUtils.isEmpty(getUsername()) - && StringUtils.isEmpty(getPassword())) { - return null; + StringBuilder ret = new StringBuilder(); + + ret.append(getUserInformation()); + + if (StringUtils.isNotEmpty(getHost())) { + if (StringUtils.isNotEmpty(getUsername()) || StringUtils.isNotEmpty(getPassword())) { + ret.append("@"); + } + ret.append(getHost()); + if (getPort() != 0) { + ret.append(":"); + ret.append(getPort()); + } } - return (getUsername() == null ? "" : getUsername()) - + ":" + (getPassword() == null ? "" : getPassword()); + + return ret.length() == 0 ? null : ret.toString(); + } + + /** + * refer to https://datatracker.ietf.org/doc/html/rfc3986 + * + * @return user information + */ + public String getUserInformation() { + StringBuilder ret = new StringBuilder(); + + if (StringUtils.isEmpty(getUsername()) && StringUtils.isEmpty(getPassword())) { + return ret.toString(); + } + + if (StringUtils.isNotEmpty(getUsername())) { + ret.append(getUsername()); + } + + ret.append(":"); + + if (StringUtils.isNotEmpty(getPassword())) { + ret.append(getPassword()); + } + + return ret.length() == 0 ? null : ret.toString(); } public String getHost() { @@ -1201,7 +1241,7 @@ class URL implements Serializable { boolean first = true; for (Map.Entry entry : new TreeMap<>(getParameters()).entrySet()) { if (StringUtils.isNotEmpty(entry.getKey()) - && (includes == null || includes.contains(entry.getKey()))) { + && (includes == null || includes.contains(entry.getKey()))) { if (first) { if (concat) { buf.append('?'); @@ -1330,7 +1370,7 @@ class URL implements Serializable { return getServiceInterface(); } return getServiceInterface() + - COLON_SEPARATOR + getVersion(); + COLON_SEPARATOR + getVersion(); } /** diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java index 9dcf5686a6..e78ab5d80c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java @@ -393,8 +393,8 @@ public class URLTest { URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); assertURLStrDecoder(url1); assertThat(url1.toString(), anyOf( - equalTo("dubbo://10.20.130.230:20880/context/path?version=1.0.0&application=morgan"), - equalTo("dubbo://10.20.130.230:20880/context/path?application=morgan&version=1.0.0")) + equalTo("dubbo://10.20.130.230:20880/context/path?version=1.0.0&application=morgan"), + equalTo("dubbo://10.20.130.230:20880/context/path?application=morgan&version=1.0.0")) ); } @@ -403,8 +403,8 @@ public class URLTest { URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); assertURLStrDecoder(url1); assertThat(url1.toFullString(), anyOf( - equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"), - equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&version=1.0.0")) + equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"), + equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&version=1.0.0")) ); } @@ -935,21 +935,21 @@ public class URLTest { Assertions.assertEquals(url4, url5); URL url6 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=1599556506417"); + "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=1599556506417"); URL url7 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); + "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); assertEquals(url6, url7); URL url8 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); + "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); assertNotEquals(url7, url8); URL url9 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=true&dubbo=2.0.2&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); + "dubbo-demo-api-consumer&category=consumers&check=true&dubbo=2.0.2&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); assertNotEquals(url8, url9); } @@ -1014,31 +1014,32 @@ public class URLTest { assertFalse(actual1); assertTrue(actual2); } + @Test public void testHashcode() { URL url1 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=1599556506417"); + "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=1599556506417"); URL url2 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); + "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); assertEquals(url1.hashCode(), url2.hashCode()); URL url3 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); + "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); assertNotEquals(url2.hashCode(), url3.hashCode()); URL url4 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" + - "dubbo-demo-api-consumer&category=consumers&check=true&dubbo=2.0.2&interface=" + - "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); + "dubbo-demo-api-consumer&category=consumers&check=true&dubbo=2.0.2&interface=" + + "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false×tamp=2299556506417"); assertNotEquals(url3.hashCode(), url4.hashCode()); } @Test public void testParameterContainPound() { URL url = URL.valueOf( - "dubbo://ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan£=abcd#efg&protocol=registry"); + "dubbo://ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan£=abcd#efg&protocol=registry"); Assertions.assertEquals("abcd#efg", url.getParameter("pound")); Assertions.assertEquals("registry", url.getParameter("protocol")); } @@ -1048,4 +1049,37 @@ public class URLTest { URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&noValue"); Assertions.assertEquals("noValue", url.getParameter("noValue")); } + + @Test + public void testGetAuthority() { + URL url = URL.valueOf("admin1:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals("admin1:hello1234@10.20.130.230:20880", url.getAuthority()); + + URL urlWithoutUsername = URL.valueOf(":hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals(":hello1234@10.20.130.230:20880", urlWithoutUsername.getAuthority()); + + URL urlWithoutPassword = URL.valueOf("admin1:@10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals("admin1:@10.20.130.230:20880", urlWithoutPassword.getAuthority()); + + URL urlWithoutUserInformation = URL.valueOf("10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals("10.20.130.230:20880", urlWithoutUserInformation.getAuthority()); + + URL urlWithoutPort = URL.valueOf("admin1:hello1234@10.20.130.230/context/path?version=1.0.0&application=app1"); + assertEquals("admin1:hello1234@10.20.130.230", urlWithoutPort.getAuthority()); + } + + @Test + public void testGetUserInformation() { + URL url = URL.valueOf("admin1:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals("admin1:hello1234", url.getUserInformation()); + + URL urlWithoutUsername = URL.valueOf(":hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals(":hello1234@10.20.130.230:20880", urlWithoutUsername.getAuthority()); + + URL urlWithoutPassword = URL.valueOf("admin1:@10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals("admin1:@10.20.130.230:20880", urlWithoutPassword.getAuthority()); + + URL urlWithoutUserInformation = URL.valueOf("10.20.130.230:20880/context/path?version=1.0.0&application=app1"); + assertEquals("10.20.130.230:20880", urlWithoutUserInformation.getAuthority()); + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/URL.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/URL.java index 42bab29301..361cd0776d 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/URL.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/URL.java @@ -116,7 +116,8 @@ public class URL extends org.apache.dubbo.common.URL { @Override public String getAuthority() { - return super.getAuthority(); + // Compatible with old version logic:The previous Authority only contained username and password information. + return super.getUserInformation(); } @Override @@ -626,6 +627,6 @@ public class URL extends org.apache.dubbo.common.URL { public org.apache.dubbo.common.URL getOriginalURL() { return new org.apache.dubbo.common.URL(super.getProtocol(), super.getUsername(), super.getPassword(), - super.getHost(), super.getPort(), super.getPath(), super.getParameters()); + super.getHost(), super.getPort(), super.getPath(), super.getParameters()); } } diff --git a/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/Curator5ZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/Curator5ZookeeperClient.java index 168ce14aa6..79fe1080bd 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/Curator5ZookeeperClient.java +++ b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/Curator5ZookeeperClient.java @@ -71,9 +71,9 @@ public class Curator5ZookeeperClient extends AbstractZookeeperClient 0) { - builder = builder.authorization("digest", authority.getBytes()); + String userInformation = url.getUserInformation(); + if (userInformation != null && userInformation.length() > 0) { + builder = builder.authorization("digest", userInformation.getBytes()); } client = builder.build(); client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url)); diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java index 433def22d6..cbf770a049 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java @@ -71,9 +71,9 @@ public class CuratorZookeeperClient extends AbstractZookeeperClient 0) { - builder = builder.authorization("digest", authority.getBytes()); + String userInformation = url.getUserInformation(); + if (userInformation != null && userInformation.length() > 0) { + builder = builder.authorization("digest", userInformation.getBytes()); } client = builder.build(); client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url));