diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java
index e02ec74a65..29b1993ca6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java
@@ -34,6 +34,8 @@ public interface QosConstants {
String ANONYMOUS_ACCESS_PERMISSION_LEVEL = "qos.anonymous.access.permission.level";
+ String ANONYMOUS_ACCESS_ALLOW_COMMANDS = "qos.anonymous.access.allow.commands";
+
String QOS_ENABLE_COMPATIBLE = "qos-enable";
String QOS_HOST_COMPATIBLE = "qos-host";
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
index 63dcfb5375..7336c6d144 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
@@ -55,6 +55,7 @@ import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_COMPATIBLE;
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST;
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST_COMPATIBLE;
+import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_ALLOW_COMMANDS;
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL;
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL_COMPATIBLE;
import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
@@ -170,6 +171,11 @@ public class ApplicationConfig extends AbstractConfig {
*/
private String qosAnonymousAccessPermissionLevel;
+ /**
+ * the anonymous(any foreign ip) allow commands, default is empty, can not access any cmd
+ */
+ private String qosAnonymousAllowCommands;
+
/**
* Customized parameters
*/
@@ -472,6 +478,15 @@ public class ApplicationConfig extends AbstractConfig {
this.qosAnonymousAccessPermissionLevel = qosAnonymousAccessPermissionLevel;
}
+ @Parameter(key = ANONYMOUS_ACCESS_ALLOW_COMMANDS)
+ public String getQosAnonymousAllowCommands() {
+ return qosAnonymousAllowCommands;
+ }
+
+ public void setQosAnonymousAllowCommands(String qosAnonymousAllowCommands) {
+ this.qosAnonymousAllowCommands = qosAnonymousAllowCommands;
+ }
+
/**
* The format is the same as the springboot, including: getQosEnableCompatible(), getQosPortCompatible(), getQosAcceptForeignIpCompatible().
*
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 8ba022c68f..141b5d5169 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -547,6 +547,12 @@
+
+
+
+
+
+
diff --git a/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java b/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java
index 476079aa14..69f9b10e19 100644
--- a/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java
+++ b/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java
@@ -38,6 +38,9 @@ public class QosConfiguration {
// the default value is Cmd.PermissionLevel.PUBLIC, can only access PUBLIC level cmd
private PermissionLevel anonymousAccessPermissionLevel = PermissionLevel.PUBLIC;
+ // the allow commands for anonymous access, the delimiter is colon(,)
+ private String anonymousAllowCommands;
+
private QosConfiguration() {
}
@@ -46,6 +49,7 @@ public class QosConfiguration {
this.acceptForeignIp = builder.isAcceptForeignIp();
this.acceptForeignIpWhitelist = builder.getAcceptForeignIpWhitelist();
this.anonymousAccessPermissionLevel = builder.getAnonymousAccessPermissionLevel();
+ this.anonymousAllowCommands = builder.getAnonymousAllowCommands();
buildPredicate();
}
@@ -93,6 +97,10 @@ public class QosConfiguration {
return acceptForeignIp;
}
+ public String getAnonymousAllowCommands() {
+ return anonymousAllowCommands;
+ }
+
public static Builder builder() {
return new Builder();
}
@@ -103,6 +111,7 @@ public class QosConfiguration {
private boolean acceptForeignIp;
private String acceptForeignIpWhitelist;
private PermissionLevel anonymousAccessPermissionLevel = PermissionLevel.PUBLIC;
+ private String anonymousAllowCommands;
private Builder() {
}
@@ -127,6 +136,11 @@ public class QosConfiguration {
return this;
}
+ public Builder anonymousAllowCommands(String anonymousAllowCommands) {
+ this.anonymousAllowCommands = anonymousAllowCommands;
+ return this;
+ }
+
public QosConfiguration build() {
return new QosConfiguration(this);
}
@@ -146,5 +160,9 @@ public class QosConfiguration {
public PermissionLevel getAnonymousAccessPermissionLevel() {
return anonymousAccessPermissionLevel;
}
+
+ public String getAnonymousAllowCommands() {
+ return anonymousAllowCommands;
+ }
}
}
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java
index 8efd756e00..61736f2247 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java
@@ -16,13 +16,16 @@
*/
package org.apache.dubbo.qos.permission;
-import io.netty.channel.Channel;
+import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.qos.api.CommandContext;
import org.apache.dubbo.qos.api.PermissionLevel;
import org.apache.dubbo.qos.api.QosConfiguration;
+import io.netty.channel.Channel;
+
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.util.Arrays;
import java.util.Optional;
public class DefaultAnonymousAccessPermissionChecker implements PermissionChecker {
@@ -37,6 +40,15 @@ public class DefaultAnonymousAccessPermissionChecker implements PermissionChecke
.orElse(null);
QosConfiguration qosConfiguration = commandContext.getQosConfiguration();
+ String anonymousAllowCommands = qosConfiguration.getAnonymousAllowCommands();
+ if (StringUtils.isNotEmpty(anonymousAllowCommands) &&
+ Arrays.stream(anonymousAllowCommands.split(","))
+ .filter(StringUtils::isNotEmpty)
+ .map(String::trim)
+ .anyMatch(cmd -> cmd.equals(commandContext.getCommandName()))) {
+ return true;
+ }
+
PermissionLevel currentLevel = qosConfiguration.getAnonymousAccessPermissionLevel();
// Local has private permission
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java
index ef2f35c3dd..127fa8bb42 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java
@@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.QOS_FAILED_START_SERVER;
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST;
+import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_ALLOW_COMMANDS;
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL;
import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST;
@@ -119,6 +120,7 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware {
boolean acceptForeignIp = Boolean.parseBoolean(url.getParameter(ACCEPT_FOREIGN_IP, "false"));
String acceptForeignIpWhitelist = url.getParameter(ACCEPT_FOREIGN_IP_WHITELIST, StringUtils.EMPTY_STRING);
String anonymousAccessPermissionLevel = url.getParameter(ANONYMOUS_ACCESS_PERMISSION_LEVEL, PermissionLevel.PUBLIC.name());
+ String anonymousAllowCommands = url.getParameter(ANONYMOUS_ACCESS_ALLOW_COMMANDS, StringUtils.EMPTY_STRING);
Server server = frameworkModel.getBeanFactory().getBean(Server.class);
if (server.isStarted()) {
@@ -130,6 +132,7 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware {
server.setAcceptForeignIp(acceptForeignIp);
server.setAcceptForeignIpWhitelist(acceptForeignIpWhitelist);
server.setAnonymousAccessPermissionLevel(anonymousAccessPermissionLevel);
+ server.setAnonymousAllowCommands(anonymousAllowCommands);
server.start();
} catch (Throwable throwable) {
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java
index 4dc03d1cd7..65e7e3b9fa 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java
@@ -58,6 +58,8 @@ public class Server {
private String anonymousAccessPermissionLevel = PermissionLevel.NONE.name();
+ private String anonymousAllowCommands = StringUtils.EMPTY_STRING;
+
private EventLoopGroup boss;
private EventLoopGroup worker;
@@ -108,6 +110,7 @@ public class Server {
.acceptForeignIp(acceptForeignIp)
.acceptForeignIpWhitelist(acceptForeignIpWhitelist)
.anonymousAccessPermissionLevel(anonymousAccessPermissionLevel)
+ .anonymousAllowCommands(anonymousAllowCommands)
.build()
));
}
@@ -167,6 +170,10 @@ public class Server {
this.anonymousAccessPermissionLevel = anonymousAccessPermissionLevel;
}
+ public void setAnonymousAllowCommands(String anonymousAllowCommands) {
+ this.anonymousAllowCommands = anonymousAllowCommands;
+ }
+
public String getWelcome() {
return welcome;
}
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java
index 11f466ca39..eef2013fde 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java
@@ -16,10 +16,11 @@
*/
package org.apache.dubbo.qos.permission;
-import io.netty.channel.Channel;
import org.apache.dubbo.qos.api.CommandContext;
import org.apache.dubbo.qos.api.PermissionLevel;
import org.apache.dubbo.qos.api.QosConfiguration;
+
+import io.netty.channel.Channel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@@ -79,5 +80,26 @@ class DefaultAnonymousAccessPermissionCheckerTest {
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC));
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED));
Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PRIVATE));
+
+ Mockito.when(qosConfiguration.getAcceptForeignIpWhitelistPredicate()).thenReturn(ip -> false);
+ Mockito.when(qosConfiguration.getAnonymousAllowCommands()).thenReturn("test1,test2");
+
+ Mockito.when(commandContext.getCommandName()).thenReturn("test1");
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE));
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC));
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED));
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PRIVATE));
+
+ Mockito.when(commandContext.getCommandName()).thenReturn("test2");
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE));
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC));
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED));
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PRIVATE));
+
+ Mockito.when(commandContext.getCommandName()).thenReturn("test");
+ Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE));
+ Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PUBLIC));
+ Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PROTECTED));
+ Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PRIVATE));
}
}