This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new d04ae4f3d [SCB-2813]fix ak/sk and rbac problems (#4096)
d04ae4f3d is described below

commit d04ae4f3d0ccddb93a46d8b8e7d617209ef29351
Author: liubao68 <[email protected]>
AuthorDate: Wed Dec 6 14:04:51 2023 +0800

    [SCB-2813]fix ak/sk and rbac problems (#4096)
---
 .../gateway/src/main/resources/application.yml     |  15 +-
 .../servicecomb/samples/ConsumerConfigIT.java      |  10 +-
 .../apache/servicecomb/samples/HelloWorldIT.java   |   6 +-
 demo/demo-cse-v2/README.md                         |   8 -
 demo/demo-cse-v2/pom.xml                           |  12 +
 .../servicecomb/samples/ConsumerConfigIT.java      |  22 +-
 .../apache/servicecomb/samples/HelloWorldIT.java   |   2 +-
 .../multiServiceCenterClient/SC2Configuration.java |   4 +-
 .../servicestage/AKSKAuthHeaderProvider.java       |  28 +--
 .../servicestage/RBACBootStrapService.java         | 259 +++++++++++++++++++++
 .../servicestage/ServiceStageConfiguration.java    |   6 -
 ...iguration.java => TokenAuthHeaderProvider.java} |  29 ++-
 .../servicestage/TokenCacheManager.java            | 209 +++++++++++++++++
 ....servicecomb.foundation.auth.AuthHeaderProvider |  19 ++
 ...rvicecomb.foundation.bootstrap.BootStrapService |  19 ++
 .../servicestage/TestAKSKAuthHeaderProvider.java   |   6 +-
 .../servicecomb/registry/sc/SCClientUtils.java     |  65 +++++-
 .../servicecomb/registry/sc/SCConfiguration.java   |   4 +-
 18 files changed, 649 insertions(+), 74 deletions(-)

diff --git a/demo/demo-cse-v1/gateway/src/main/resources/application.yml 
b/demo/demo-cse-v1/gateway/src/main/resources/application.yml
index 73545ed33..d35fba881 100644
--- a/demo/demo-cse-v1/gateway/src/main/resources/application.yml
+++ b/demo/demo-cse-v1/gateway/src/main/resources/application.yml
@@ -50,9 +50,16 @@ servicecomb:
               microserviceName: consumer
               versionRule: 0.0.0+
 
-  router:
-    type: router
-    header: canary
+  matchGroup:
+    canary-header: |
+      matches:
+        - headers:
+            canary: 
+              prefix: ""
+  mapper:
+    canary-header: |
+      target:
+        canary: $H{canary}
 
   # Configure AK/SK credentials if needed. Default not enabled.
   credentials:
@@ -60,4 +67,4 @@ servicecomb:
     accessKey: ${CREDENTIALS_AK}
     secretKey: ${CREDENTIALS_SK}
     akskCustomCipher: default
-    project: cn-south-1
\ No newline at end of file
+    project: cn-south-1
diff --git 
a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
 
b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
index 64cc9cc30..2aff8c259 100644
--- 
a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
+++ 
b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
@@ -38,11 +38,11 @@ public class ConsumerConfigIT implements 
CategorizedTestCase {
   @SuppressWarnings("unchecked")
   private void testConfig() {
     String result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v1.test.foo", String.class);
-    TestMgr.check("\"foo\"", result);
+    TestMgr.check("foo", result);
     result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v1.test.bar", String.class);
-    TestMgr.check("\"bar\"", result);
+    TestMgr.check("bar", result);
     result = template.getForObject(Config.GATEWAY_URL + 
"/dynamicString?key=cse.v1.test.dynamicString", String.class);
-    TestMgr.check("\"a,b\"", result);
+    TestMgr.check("a,b", result);
 
     List<String> listResult = template
         .getForObject(Config.GATEWAY_URL + "/dynamicArray", List.class);
@@ -53,8 +53,8 @@ public class ConsumerConfigIT implements CategorizedTestCase {
 
   private void testFooBar() {
     String result = template.getForObject(Config.GATEWAY_URL + "/foo", 
String.class);
-    TestMgr.check("\"foo\"", result);
+    TestMgr.check("foo", result);
     result = template.getForObject(Config.GATEWAY_URL + "/bar", String.class);
-    TestMgr.check("\"bar\"", result);
+    TestMgr.check("bar", result);
   }
 }
diff --git 
a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
 
b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
index f744d4bca..c49295d11 100644
--- 
a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
+++ 
b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
@@ -45,7 +45,7 @@ public class HelloWorldIT implements CategorizedTestCase {
       HttpEntity<Object> entity = new HttpEntity<>(headers);
       String result = template
           .exchange(Config.GATEWAY_URL + "/sayHello?name=World", 
HttpMethod.GET, entity, String.class).getBody();
-      TestMgr.check("\"Hello World\"", result);
+      TestMgr.check("Hello World", result);
     }
   }
 
@@ -59,9 +59,9 @@ public class HelloWorldIT implements CategorizedTestCase {
       HttpEntity<Object> entity = new HttpEntity<>(headers);
       String result = template
           .exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", 
HttpMethod.GET, entity, String.class).getBody();
-      if (result.equals("\"Hello Canary World\"")) {
+      if (result.equals("Hello Canary World")) {
         oldCount++;
-      } else if (result.equals("\"Hello Canary in canary World\"")) {
+      } else if (result.equals("Hello Canary in canary World")) {
         newCount++;
       } else {
         TestMgr.fail("not expected result testHelloWorldCanary");
diff --git a/demo/demo-cse-v2/README.md b/demo/demo-cse-v2/README.md
index 001b59da9..9636d71b7 100644
--- a/demo/demo-cse-v2/README.md
+++ b/demo/demo-cse-v2/README.md
@@ -52,14 +52,6 @@ cse:
       priority: v3
 ```
 
-  * 自定义配置:priority3.yaml,labels: 
app=demo-java-chassis-cse-v2,environment=,service=consumer,extra=。类型为 yaml。 
-```yaml
-cse:
-  v2:
-    test:
-      priority: v4
-```
-
 * 应用级配置:consumerApp.yaml,应用选择demo-java-chassis-cse-v2。类型为 yaml。
 ```yaml
 cse:
diff --git a/demo/demo-cse-v2/pom.xml b/demo/demo-cse-v2/pom.xml
index 49c233ad4..83980c915 100644
--- a/demo/demo-cse-v2/pom.xml
+++ b/demo/demo-cse-v2/pom.xml
@@ -37,10 +37,22 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>registry-service-center</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>config-kie</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-slf4j-impl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
   </dependencies>
 
   <modules>
diff --git 
a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
 
b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
index 3e10063a5..16b138864 100644
--- 
a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
+++ 
b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
@@ -35,29 +35,29 @@ public class ConsumerConfigIT implements 
CategorizedTestCase {
 
   private void testConfig() {
     String result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v2.test.foo", String.class);
-    TestMgr.check("\"foo\"", result);
+    TestMgr.check("foo", result);
     result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v2.test.bar", String.class);
-    TestMgr.check("\"bar\"", result);
+    TestMgr.check("bar", result);
     result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v2.test.priority", String.class);
-    TestMgr.check("\"v1\"", result);
+    TestMgr.check("v1", result);
     result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v2.test.common", String.class);
-    TestMgr.check("\"common\"", result);
+    TestMgr.check("common", result);
     result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v2.test.extra", String.class);
-    TestMgr.check("\"common\"", result);
+    TestMgr.check("common", result);
     result = template.getForObject(Config.GATEWAY_URL + 
"/config?key=cse.v2.test.priority1", String.class);
-    TestMgr.check("\"v2\"", result);
+    TestMgr.check("v2", result);
   }
 
   private void testFooBar() {
     String result = template.getForObject(Config.GATEWAY_URL + "/bar", 
String.class);
-    TestMgr.check("\"bar\"", result);
+    TestMgr.check("bar", result);
     result = template.getForObject(Config.GATEWAY_URL + "/foo", String.class);
-    TestMgr.check("\"foo\"", result);
+    TestMgr.check("foo", result);
     result = template.getForObject(Config.GATEWAY_URL + "/priority", 
String.class);
-    TestMgr.check("\"v1\"", result);
+    TestMgr.check("v1", result);
     result = template.getForObject(Config.GATEWAY_URL + "/common", 
String.class);
-    TestMgr.check("\"common\"", result);
+    TestMgr.check("common", result);
     result = template.getForObject(Config.GATEWAY_URL + "/extra", 
String.class);
-    TestMgr.check("\"common\"", result);
+    TestMgr.check("common", result);
   }
 }
diff --git 
a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
 
b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
index e667095b5..59d06bb1e 100644
--- 
a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
+++ 
b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
@@ -35,6 +35,6 @@ public class HelloWorldIT implements CategorizedTestCase {
   private void testHelloWorld() {
     String result = template
         .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", 
String.class);
-    TestMgr.check("\"Hello World\"", result);
+    TestMgr.check("Hello World", result);
   }
 }
diff --git 
a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Configuration.java
 
b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Configuration.java
index 754134c4a..db7fc11df 100644
--- 
a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Configuration.java
+++ 
b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Configuration.java
@@ -48,8 +48,8 @@ public class SC2Configuration {
   @Bean
   public ServiceCenterClient serviceCenterClient2(
       @Qualifier("scConfigurationProperties2") SCConfigurationProperties 
scConfigurationProperties2,
-      List<AuthHeaderProvider> authHeaderProviders, Environment environment) {
-    return SCClientUtils.serviceCenterClient(scConfigurationProperties2, 
authHeaderProviders, environment);
+      Environment environment) {
+    return SCClientUtils.serviceCenterClient(scConfigurationProperties2, 
environment);
   }
 
   @Bean
diff --git 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java
 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java
index e192a4fbd..98d71e6b2 100644
--- 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java
+++ 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java
@@ -17,7 +17,6 @@
 
 package org.apache.servicecomb.huaweicloud.servicestage;
 
-import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
@@ -33,12 +32,13 @@ import 
org.apache.servicecomb.foundation.auth.AuthHeaderProvider;
 import org.apache.servicecomb.foundation.auth.Cipher;
 import org.apache.servicecomb.foundation.auth.DefaultCipher;
 import org.apache.servicecomb.foundation.auth.ShaAKSKCipher;
+import org.apache.servicecomb.foundation.bootstrap.BootStrapService;
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.env.Environment;
 
-public class AKSKAuthHeaderProvider implements AuthHeaderProvider {
+public class AKSKAuthHeaderProvider implements AuthHeaderProvider, 
BootStrapService {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(AKSKAuthHeaderProvider.class);
 
   private static final String CONFIG_AKSK_ENABLED = 
"servicecomb.credentials.akskEnabled";
@@ -61,21 +61,20 @@ public class AKSKAuthHeaderProvider implements 
AuthHeaderProvider {
 
   private static final String X_SERVICE_PROJECT = "X-Service-Project";
 
+  private static Environment environment;
+
   private final Map<String, String> headers = new HashMap<>();
 
-  private boolean enabled;
+  private boolean enabled = true;
 
   private boolean loaded = false;
 
-  private final Environment environment;
-
-  public AKSKAuthHeaderProvider(Environment environment) {
-    this.environment = environment;
-    this.enabled = environment.getProperty(CONFIG_AKSK_ENABLED, boolean.class, 
true);
+  public AKSKAuthHeaderProvider() {
   }
 
   public Map<String, String> authHeaders() {
-    if (!enabled) {
+    if (enabled && !environment.getProperty(CONFIG_AKSK_ENABLED, 
boolean.class, true)) {
+      enabled = false;
       return headers;
     }
 
@@ -127,11 +126,7 @@ public class AKSKAuthHeaderProvider implements 
AuthHeaderProvider {
     if (StringUtils.isEmpty(project)) {
       return project;
     }
-    try {
-      return URLEncoder.encode(project, "UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      return project;
-    }
+    return URLEncoder.encode(project, StandardCharsets.UTF_8);
   }
 
   private Cipher findCipher() {
@@ -155,4 +150,9 @@ public class AKSKAuthHeaderProvider implements 
AuthHeaderProvider {
       throw new IllegalArgumentException("Can not encode ak sk. Please check 
the value is correct.", e);
     }
   }
+
+  @Override
+  public void startup(Environment environment) {
+    AKSKAuthHeaderProvider.environment = environment;
+  }
 }
diff --git 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/RBACBootStrapService.java
 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/RBACBootStrapService.java
new file mode 100644
index 000000000..b772a0eb0
--- /dev/null
+++ 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/RBACBootStrapService.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *     http://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.apache.servicecomb.huaweicloud.servicestage;
+
+import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.servicecomb.foundation.auth.Cipher;
+import org.apache.servicecomb.foundation.auth.DefaultCipher;
+import org.apache.servicecomb.foundation.bootstrap.BootStrapService;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
+import org.apache.servicecomb.foundation.ssl.SSLCustom;
+import org.apache.servicecomb.foundation.ssl.SSLOption;
+import org.apache.servicecomb.foundation.vertx.VertxConst;
+import 
org.apache.servicecomb.http.client.auth.DefaultRequestAuthHeaderProvider;
+import 
org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;
+import org.apache.servicecomb.http.client.common.HttpTransport;
+import org.apache.servicecomb.http.client.common.HttpTransportFactory;
+import 
org.apache.servicecomb.service.center.client.ServiceCenterAddressManager;
+import org.apache.servicecomb.service.center.client.ServiceCenterClient;
+import org.apache.servicecomb.service.center.client.ServiceCenterRawClient;
+import org.springframework.core.env.Environment;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class RBACBootStrapService implements BootStrapService {
+  private static final String RBAC_ADDRESS = 
"servicecomb.service.registry.address";
+
+  public static final String DEFAULT_REGISTRY_NAME = "default";
+
+  public static final String RBAC_ENABLED = 
"servicecomb.credentials.rbac.enabled";
+
+  public static final String ACCOUNT_NAME_KEY = 
"servicecomb.credentials.account.name";
+
+  public static final String PASSWORD_KEY = 
"servicecomb.credentials.account.password";
+
+  public static final String CIPHER_KEY = "servicecomb.credentials.cipher";
+
+  public static final String PROJECT_KEY = "servicecomb.credentials.project";
+
+  private static final String SSL_TAG = "sc.consumer";
+
+  @Override
+  public void startup(Environment environment) {
+    if (!getBooleanProperty(environment, false, RBAC_ENABLED)) {
+      return;
+    }
+
+    ServiceCenterAddressManager addressManager = 
createAddressManager(environment);
+    SSLProperties sslProperties = createSSLProperties(environment);
+    sslProperties.setEnabled(addressManager.sslEnabled());
+
+    ServiceCenterClient serviceCenterClient =
+        new ServiceCenterClient(new ServiceCenterRawClient.Builder()
+            .setTenantName("default")
+            .setAddressManager(addressManager)
+            .setHttpTransport(createHttpTransport(environment, 
sslProperties)).build());
+
+    Map<String, ServiceCenterClient> clients = new HashMap<>(1);
+    clients.put(DEFAULT_REGISTRY_NAME, serviceCenterClient);
+    TokenCacheManager.getInstance().setServiceCenterClients(clients);
+    TokenCacheManager.getInstance().addTokenCache(
+        DEFAULT_REGISTRY_NAME,
+        getStringProperty(environment, null, ACCOUNT_NAME_KEY),
+        getStringProperty(environment, null, PASSWORD_KEY),
+        getCipher(getStringProperty(environment, DefaultCipher.CIPHER_NAME, 
CIPHER_KEY)));
+  }
+
+  private static HttpTransport createHttpTransport(Environment environment, 
SSLProperties sslProperties) {
+    if (isProxyEnable(environment)) {
+      HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().
+          
setDefaultRequestConfig(HttpTransportFactory.defaultRequestConfig().build());
+      HttpHost proxy = new HttpHost(getProxyHost(environment),
+          getProxyPort(environment), "http");  // now only support http proxy
+      httpClientBuilder.setProxy(proxy);
+      CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+      credentialsProvider.setCredentials(new AuthScope(proxy),
+          new UsernamePasswordCredentials(getProxyUsername(environment),
+              getProxyPasswd(environment)));
+      httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+
+      return HttpTransportFactory
+          .createHttpTransport(sslProperties,
+              new DefaultRequestAuthHeaderProvider(), httpClientBuilder);
+    }
+
+    return HttpTransportFactory
+        .createHttpTransport(sslProperties,
+            new DefaultRequestAuthHeaderProvider(), 
HttpTransportFactory.defaultRequestConfig().build());
+  }
+
+  @VisibleForTesting
+  Cipher getCipher(String cipherName) {
+    if (DefaultCipher.CIPHER_NAME.equals(cipherName)) {
+      return DefaultCipher.getInstance();
+    }
+
+    List<Cipher> ciphers = 
SPIServiceUtils.getOrLoadSortedService(Cipher.class);
+    return ciphers.stream().filter(c -> 
c.name().equals(cipherName)).findFirst()
+        .orElseThrow(() -> new IllegalArgumentException("failed to find cipher 
named " + cipherName));
+  }
+
+  private ServiceCenterAddressManager createAddressManager(Environment 
environment) {
+    return new ServiceCenterAddressManager(getProjectName(environment),
+        getRBACAddressList(environment), EventManager.getEventBus());
+  }
+
+  private SSLProperties createSSLProperties(Environment environment) {
+    SSLProperties sslProperties = new SSLProperties();
+
+    SSLOption option = new SSLOption();
+    option.setEngine(getStringProperty(environment,
+        DEFAULT_OPTION.getEngine(),
+        "ssl." + SSL_TAG + ".engine",
+        "ssl.engine"));
+    option.setProtocols(
+        getStringProperty(environment,
+            DEFAULT_OPTION.getProtocols(),
+            "ssl." + SSL_TAG + ".protocols",
+            "ssl.protocols"));
+    option.setCiphers(
+        getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + 
SSL_TAG + ".ciphers", "ssl.ciphers"));
+    option.setAuthPeer(
+        getBooleanProperty(environment, DEFAULT_OPTION.isAuthPeer(), "ssl." + 
SSL_TAG + ".authPeer", "ssl.authPeer"));
+    option.setCheckCNHost(
+        getBooleanProperty(environment,
+            DEFAULT_OPTION.isCheckCNHost(),
+            "ssl." + SSL_TAG + ".checkCN.host",
+            "ssl.checkCN.host"));
+    option.setCheckCNWhite(
+        getBooleanProperty(environment,
+            DEFAULT_OPTION.isCheckCNWhite(),
+            "ssl." + SSL_TAG + ".checkCN.white",
+            "ssl.checkCN.white"));
+    option.setCheckCNWhiteFile(getStringProperty(environment,
+        DEFAULT_OPTION.getCiphers(),
+        "ssl." + SSL_TAG + ".checkCN.white.file",
+        "ssl.checkCN.white.file"));
+    option.setAllowRenegociate(getBooleanProperty(environment,
+        DEFAULT_OPTION.isAllowRenegociate(),
+        "ssl." + SSL_TAG + ".allowRenegociate",
+        "ssl.allowRenegociate"));
+    option.setStorePath(
+        getStringProperty(environment,
+            DEFAULT_OPTION.getStorePath(),
+            "ssl." + SSL_TAG + ".storePath",
+            "ssl.storePath"));
+    option.setClientAuth(
+        getStringProperty(environment,
+            DEFAULT_OPTION.getClientAuth(),
+            "ssl." + SSL_TAG + ".clientAuth",
+            "ssl.clientAuth"));
+    option.setTrustStore(
+        getStringProperty(environment,
+            DEFAULT_OPTION.getTrustStore(),
+            "ssl." + SSL_TAG + ".trustStore",
+            "ssl.trustStore"));
+    option.setTrustStoreType(getStringProperty(environment,
+        DEFAULT_OPTION.getTrustStoreType(),
+        "ssl." + SSL_TAG + ".trustStoreType",
+        "ssl.trustStoreType"));
+    option.setTrustStoreValue(getStringProperty(environment,
+        DEFAULT_OPTION.getTrustStoreValue(),
+        "ssl." + SSL_TAG + ".trustStoreValue",
+        "ssl.trustStoreValue"));
+    option.setKeyStore(
+        getStringProperty(environment, DEFAULT_OPTION.getKeyStore(), "ssl." + 
SSL_TAG + ".keyStore", "ssl.keyStore"));
+    option.setKeyStoreType(
+        getStringProperty(environment,
+            DEFAULT_OPTION.getKeyStoreType(),
+            "ssl." + SSL_TAG + ".keyStoreType",
+            "ssl.keyStoreType"));
+    option.setKeyStoreValue(getStringProperty(environment,
+        DEFAULT_OPTION.getKeyStoreValue(),
+        "ssl." + SSL_TAG + ".keyStoreValue",
+        "ssl.keyStoreValue"));
+    option.setCrl(getStringProperty(environment, DEFAULT_OPTION.getCrl(), 
"ssl." + SSL_TAG + ".crl", "ssl.crl"));
+    option.setSslCustomClass(
+        getStringProperty(environment, null, "ssl." + SSL_TAG + 
".sslCustomClass", "ssl.sslCustomClass"));
+
+    sslProperties.setSslOption(option);
+    
sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass()));
+    return sslProperties;
+  }
+
+  private String getStringProperty(Environment environment, String 
defaultValue, String... keys) {
+    for (String key : keys) {
+      if (environment.getProperty(key) != null) {
+        return environment.getProperty(key);
+      }
+    }
+    return defaultValue;
+  }
+
+  private boolean getBooleanProperty(Environment environment, boolean 
defaultValue, String... keys) {
+    for (String key : keys) {
+      if (environment.getProperty(key) != null) {
+        return Boolean.parseBoolean(environment.getProperty(key));
+      }
+    }
+    return defaultValue;
+  }
+
+  private String getProjectName(Environment environment) {
+    return getStringProperty(environment, "default", PROJECT_KEY);
+  }
+
+  private List<String> getRBACAddressList(Environment environment) {
+    String address = environment.getProperty(RBAC_ADDRESS, 
"http://127.0.0.1:30100)");
+    return Arrays.asList(address.split(","));
+  }
+
+
+  public static Boolean isProxyEnable(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_ENABLE, boolean.class, 
false);
+  }
+
+  public static String getProxyHost(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_HOST, "127.0.0.1");
+  }
+
+  public static int getProxyPort(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_PORT, int.class, 8080);
+  }
+
+  public static String getProxyUsername(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_USERNAME);
+  }
+
+  public static String getProxyPasswd(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_PASSWD);
+  }
+}
diff --git 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java
 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java
index 543507aa2..5a369b70b 100644
--- 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java
+++ 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java
@@ -18,15 +18,9 @@ package org.apache.servicecomb.huaweicloud.servicestage;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
 
 @Configuration
 public class ServiceStageConfiguration {
-  @Bean
-  public AKSKAuthHeaderProvider akskAuthHeaderProvider(Environment 
environment) {
-    return new AKSKAuthHeaderProvider(environment);
-  }
-
   @Bean
   public CasEnvVariablesAdapter casEnvVariablesAdapter() {
     return new CasEnvVariablesAdapter();
diff --git 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java
 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenAuthHeaderProvider.java
similarity index 57%
copy from 
huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java
copy to 
huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenAuthHeaderProvider.java
index 543507aa2..6698f99f8 100644
--- 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java
+++ 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenAuthHeaderProvider.java
@@ -14,21 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.servicecomb.huaweicloud.servicestage;
 
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
-@Configuration
-public class ServiceStageConfiguration {
-  @Bean
-  public AKSKAuthHeaderProvider akskAuthHeaderProvider(Environment 
environment) {
-    return new AKSKAuthHeaderProvider(environment);
-  }
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.foundation.auth.AuthHeaderProvider;
+
+public class TokenAuthHeaderProvider implements AuthHeaderProvider {
+  @Override
+  public Map<String, String> authHeaders() {
+    String token = 
TokenCacheManager.getInstance().getToken(RBACBootStrapService.DEFAULT_REGISTRY_NAME);
+    if (StringUtils.isEmpty(token)) {
+      return new HashMap<>();
+    }
 
-  @Bean
-  public CasEnvVariablesAdapter casEnvVariablesAdapter() {
-    return new CasEnvVariablesAdapter();
+    HashMap<String, String> header = new HashMap<>();
+    header.put("Authorization", "Bearer " + token);
+    return Collections.unmodifiableMap(header);
   }
 }
diff --git 
a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenCacheManager.java
 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenCacheManager.java
new file mode 100644
index 000000000..9e92e0303
--- /dev/null
+++ 
b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenCacheManager.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *     http://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.apache.servicecomb.huaweicloud.servicestage;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.foundation.auth.Cipher;
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.service.center.client.OperationEvents;
+import org.apache.servicecomb.service.center.client.ServiceCenterClient;
+import org.apache.servicecomb.service.center.client.model.RbacTokenRequest;
+import org.apache.servicecomb.service.center.client.model.RbacTokenResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.eventbus.Subscribe;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import jakarta.ws.rs.core.Response.Status;
+
+public final class TokenCacheManager {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(TokenCacheManager.class);
+
+  // special token used for special conditions
+  // e.g. un-authorized: will query token after token expired period
+  // e.g. not found:  will query token after token expired period
+  public static final String INVALID_TOKEN = "";
+
+  private static final TokenCacheManager INSTANCE = new TokenCacheManager();
+
+
+  private final Map<String, TokenCache> tokenCacheMap;
+
+  private Map<String, ServiceCenterClient> serviceCenterClients;
+
+  public static TokenCacheManager getInstance() {
+    return INSTANCE;
+  }
+
+  private TokenCacheManager() {
+    tokenCacheMap = new ConcurrentHashMapEx<>();
+  }
+
+  public void setServiceCenterClients(Map<String, ServiceCenterClient> 
serviceCenterClients) {
+    this.serviceCenterClients = serviceCenterClients;
+  }
+
+  public void addTokenCache(String registryName, String accountName, String 
password, Cipher cipher) {
+    Objects.requireNonNull(registryName, "registryName should not be null!");
+    if (tokenCacheMap.containsKey(registryName)) {
+      LOGGER.warn("duplicate token cache registration for 
serviceRegistry[{}]", registryName);
+      return;
+    }
+
+    tokenCacheMap.put(registryName, new TokenCache(registryName, accountName, 
password, cipher));
+  }
+
+  public String getToken(String registryName) {
+    return Optional.ofNullable(tokenCacheMap.get(registryName))
+        .map(TokenCache::getToken)
+        .orElse(null);
+  }
+
+  public class TokenCache {
+    private static final String UN_AUTHORIZED_CODE_HALF_OPEN = "401302";
+
+    private static final long TOKEN_REFRESH_TIME_IN_SECONDS = 20 * 60 * 1000;
+
+    private final String registryName;
+
+    private final String accountName;
+
+    private final String password;
+
+    private ExecutorService executorService;
+
+    private LoadingCache<String, String> cache;
+
+    private final Cipher cipher;
+
+    private int lastStatusCode;
+
+    private String lastErrorCode;
+
+    public TokenCache(String registryName, String accountName, String password,
+        Cipher cipher) {
+      this.registryName = registryName;
+      this.accountName = accountName;
+      this.password = password;
+      this.cipher = cipher;
+
+      if (enabled()) {
+        executorService = Executors.newFixedThreadPool(1, t -> new Thread(t, 
"rbac-executor-" + this.registryName) {
+          @Override
+          public void run() {
+            try {
+              super.run();
+            } catch (Throwable e) {
+              LOGGER.error("", e);
+            }
+          }
+        });
+        cache = CacheBuilder.newBuilder()
+            .maximumSize(1)
+            .refreshAfterWrite(refreshTime(), TimeUnit.MILLISECONDS)
+            .build(new CacheLoader<String, String>() {
+              @Override
+              public String load(String key) throws Exception {
+                return createHeaders();
+              }
+
+              @Override
+              public ListenableFuture<String> reload(String key, String 
oldValue) throws Exception {
+                return Futures.submit(() -> createHeaders(), executorService);
+              }
+            });
+        EventManager.getEventBus().register(this);
+      }
+    }
+
+    @Subscribe
+    public void onNotPermittedEvent(OperationEvents.UnAuthorizedOperationEvent 
event) {
+      this.executorService.submit(() -> {
+        if (lastStatusCode == Status.UNAUTHORIZED.getStatusCode() && 
UN_AUTHORIZED_CODE_HALF_OPEN
+            .equals(lastErrorCode)) {
+          cache.refresh(registryName);
+        }
+      });
+    }
+
+    private String createHeaders() {
+      LOGGER.info("start to create RBAC headers");
+
+      ServiceCenterClient serviceCenterClient = 
serviceCenterClients.get(this.registryName);
+
+      RbacTokenRequest request = new RbacTokenRequest();
+      request.setName(accountName);
+      request.setPassword(new String(cipher.decrypt(password.toCharArray())));
+
+      RbacTokenResponse rbacTokenResponse = 
serviceCenterClient.queryToken(request);
+
+      this.lastStatusCode = rbacTokenResponse.getStatusCode();
+      this.lastErrorCode = rbacTokenResponse.getErrorCode();
+
+      if (Status.UNAUTHORIZED.getStatusCode() == 
rbacTokenResponse.getStatusCode()
+          || Status.FORBIDDEN.getStatusCode() == 
rbacTokenResponse.getStatusCode()) {
+        // password wrong, do not try anymore
+        LOGGER.warn("username or password may be wrong, stop trying to query 
tokens.");
+        return INVALID_TOKEN;
+      }
+      if (Status.NOT_FOUND.getStatusCode() == 
rbacTokenResponse.getStatusCode()) {
+        // service center not support, do not try
+        LOGGER.warn("service center do not support RBAC token, you should not 
config account info");
+        return INVALID_TOKEN;
+      }
+
+      LOGGER.info("refresh token successfully {}", 
rbacTokenResponse.getStatusCode());
+      return rbacTokenResponse.getToken();
+    }
+
+    protected long refreshTime() {
+      return TOKEN_REFRESH_TIME_IN_SECONDS;
+    }
+
+    public String getToken() {
+      if (!enabled()) {
+        return null;
+      }
+
+      try {
+        return cache.get(registryName);
+      } catch (Exception e) {
+        LOGGER.error("failed to create token", e);
+        return null;
+      }
+    }
+
+    private boolean enabled() {
+      return !StringUtils.isEmpty(this.accountName)
+          && !StringUtils.isEmpty(this.password);
+    }
+  }
+}
diff --git 
a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.AuthHeaderProvider
 
b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.AuthHeaderProvider
new file mode 100644
index 000000000..a78d2c2e3
--- /dev/null
+++ 
b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.AuthHeaderProvider
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+#     http://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.
+#
+
+org.apache.servicecomb.huaweicloud.servicestage.AKSKAuthHeaderProvider
+org.apache.servicecomb.huaweicloud.servicestage.TokenAuthHeaderProvider
diff --git 
a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService
 
b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService
new file mode 100644
index 000000000..90c339ba0
--- /dev/null
+++ 
b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+#     http://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.
+#
+
+org.apache.servicecomb.huaweicloud.servicestage.RBACBootStrapService
+org.apache.servicecomb.huaweicloud.servicestage.AKSKAuthHeaderProvider
diff --git 
a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java
 
b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java
index 2495ef64d..2b82672c7 100644
--- 
a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java
+++ 
b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java
@@ -37,7 +37,8 @@ public class TestAKSKAuthHeaderProvider {
     
Mockito.when(environment.getProperty("servicecomb.credentials.akskCustomCipher",
         "default")).thenReturn("default");
 
-    AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(environment);
+    AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider();
+    provider.startup(environment);
     Assertions.assertEquals("hello", 
provider.authHeaders().get("X-Service-Project"));
   }
 
@@ -54,7 +55,8 @@ public class TestAKSKAuthHeaderProvider {
         "")).thenReturn("secret key");
     
Mockito.when(environment.getProperty("servicecomb.credentials.akskCustomCipher",
         "default")).thenReturn("default");
-    AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(environment);
+    AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider();
+    provider.startup(environment);
     Assertions.assertEquals("%E6%B5%8B%E8%AF%95", 
provider.authHeaders().get("X-Service-Project"));
   }
 }
diff --git 
a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCClientUtils.java
 
b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCClientUtils.java
index 7da39ce32..b248f4676 100644
--- 
a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCClientUtils.java
+++ 
b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCClientUtils.java
@@ -21,16 +21,27 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.foundation.auth.AuthHeaderProvider;
 import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.foundation.ssl.SSLCustom;
 import org.apache.servicecomb.foundation.ssl.SSLOption;
 import org.apache.servicecomb.foundation.ssl.SSLOptionFactory;
+import org.apache.servicecomb.foundation.vertx.VertxConst;
 import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider;
 import 
org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;
+import org.apache.servicecomb.http.client.common.HttpTransport;
+import org.apache.servicecomb.http.client.common.HttpTransportFactory;
 import 
org.apache.servicecomb.service.center.client.ServiceCenterAddressManager;
 import org.apache.servicecomb.service.center.client.ServiceCenterClient;
+import org.apache.servicecomb.service.center.client.ServiceCenterRawClient;
 import org.apache.servicecomb.service.center.client.ServiceCenterWatch;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,14 +58,60 @@ public class SCClientUtils {
 
   // add other headers needed for registration by new ServiceCenterClient(...)
   public static ServiceCenterClient 
serviceCenterClient(SCConfigurationProperties discoveryProperties,
-      List<AuthHeaderProvider> authHeaderProviders, Environment environment) {
+      Environment environment) {
     ServiceCenterAddressManager addressManager = 
createAddressManager(discoveryProperties);
 
     SSLProperties sslProperties = buildSslProperties(addressManager, 
environment);
 
-    return new ServiceCenterClient(addressManager, sslProperties,
-        getRequestAuthHeaderProvider(authHeaderProviders),
-        "default", new HashMap<>()).setEventBus(EventManager.getEventBus());
+    return new ServiceCenterClient(new ServiceCenterRawClient.Builder()
+        .setTenantName("default")
+        .setAddressManager(addressManager)
+        .setHttpTransport(createHttpTransport(environment, 
sslProperties)).build());
+  }
+
+  private static HttpTransport createHttpTransport(Environment environment, 
SSLProperties sslProperties) {
+    List<AuthHeaderProvider> authHeaderProviders = 
SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class);
+
+    if (isProxyEnable(environment)) {
+      HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().
+          
setDefaultRequestConfig(HttpTransportFactory.defaultRequestConfig().build());
+      HttpHost proxy = new HttpHost(getProxyHost(environment),
+          getProxyPort(environment), "http");  // now only support http proxy
+      httpClientBuilder.setProxy(proxy);
+      CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+      credentialsProvider.setCredentials(new AuthScope(proxy),
+          new UsernamePasswordCredentials(getProxyUsername(environment),
+              getProxyPasswd(environment)));
+      httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+
+      return HttpTransportFactory
+          .createHttpTransport(sslProperties,
+              getRequestAuthHeaderProvider(authHeaderProviders), 
httpClientBuilder);
+    }
+
+    return HttpTransportFactory
+        .createHttpTransport(sslProperties,
+            getRequestAuthHeaderProvider(authHeaderProviders), 
HttpTransportFactory.defaultRequestConfig().build());
+  }
+
+  public static Boolean isProxyEnable(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_ENABLE, boolean.class, 
false);
+  }
+
+  public static String getProxyHost(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_HOST, "127.0.0.1");
+  }
+
+  public static int getProxyPort(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_PORT, int.class, 8080);
+  }
+
+  public static String getProxyUsername(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_USERNAME);
+  }
+
+  public static String getProxyPasswd(Environment environment) {
+    return environment.getProperty(VertxConst.PROXY_PASSWD);
   }
 
   private static SSLProperties buildSslProperties(ServiceCenterAddressManager 
addressManager,
diff --git 
a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCConfiguration.java
 
b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCConfiguration.java
index ac7620ad2..6cd8965c8 100644
--- 
a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCConfiguration.java
+++ 
b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/registry/sc/SCConfiguration.java
@@ -39,8 +39,8 @@ public class SCConfiguration {
   @Bean
   public ServiceCenterClient serviceCenterClient(
       @Qualifier("scConfigurationProperties") SCConfigurationProperties 
scConfigurationProperties,
-      List<AuthHeaderProvider> authHeaderProviders, Environment environment) {
-    return SCClientUtils.serviceCenterClient(scConfigurationProperties, 
authHeaderProviders, environment);
+      Environment environment) {
+    return SCClientUtils.serviceCenterClient(scConfigurationProperties, 
environment);
   }
 
   @Bean


Reply via email to