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/incubator-servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 23bbb7f  [SCB-640]add public key black/white feature and samples (#753)
23bbb7f is described below

commit 23bbb7f375a02fc376a3827a1604bbbda3748ad2
Author: bao liu <[email protected]>
AuthorDate: Sat Jul 7 11:39:35 2018 +0800

    [SCB-640]add public key black/white feature and samples (#753)
    
    * [SCB-640]add public key black/white feature and samples
    
    * [SCB-640]add test cases and minor fixes
---
 handlers/handler-publickey-auth/pom.xml            |   5 +
 .../authentication/provider/AccessController.java  | 169 +++++++++++++++++++++
 .../provider/RSAProviderTokenManager.java          |   8 +-
 .../authentication/TestAccessController.java       | 116 ++++++++++++++
 .../authentication/TestProviderAuthHanlder.java    |   9 +-
 .../TestRSAProviderTokenManager.java               |  16 ++
 samples/pom.xml                                    |   1 +
 samples/trust-sample/README.md                     |   4 +
 .../trust-sample/customer}/pom.xml                 |  45 +++---
 .../apache/servicecomb/samples/trust/Compute.java  |  28 ++++
 .../samples/trust/consumer/CustomerMain.java       |  42 +++++
 .../main/resources/config/log4j.demo.properties    |  21 +++
 .../customer/src/main/resources/microservice.yaml  |  37 +++++
 .../trust-sample/hacker}/pom.xml                   |  49 +++---
 .../apache/servicecomb/samples/trust/Compute.java  |  28 ++++
 .../samples/trust/consumer/HackerMain.java         |  41 +++++
 .../main/resources/config/log4j.demo.properties    |  21 +++
 .../hacker/src/main/resources/microservice.yaml    |  37 +++++
 .../trust-sample}/pom.xml                          |  39 ++---
 .../trust-sample/store}/pom.xml                    |  49 +++---
 .../apache/servicecomb/samples/trust/Compute.java  |  28 ++++
 .../trust/provider/CodeFirstComputeImpl.java       |  48 ++++++
 .../samples/trust/provider/TrustMain.java          |  29 ++++
 .../main/resources/config/log4j.demo.properties    |  21 +++
 .../store/src/main/resources/microservice.yaml     |  47 ++++++
 .../cache/MicroserviceInstanceCache.java           |  39 ++++-
 .../cache/TestMicroserviceInstanceCache.java       |  72 +++++++++
 27 files changed, 953 insertions(+), 96 deletions(-)

diff --git a/handlers/handler-publickey-auth/pom.xml 
b/handlers/handler-publickey-auth/pom.xml
index 9fd5019..d4a45d0 100644
--- a/handlers/handler-publickey-auth/pom.xml
+++ b/handlers/handler-publickey-auth/pom.xml
@@ -46,6 +46,11 @@
       <artifactId>log4j</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>foundation-test-scaffolding</artifactId>
+      <scope>test</scope>
+    </dependency>
 
   </dependencies>
 
diff --git 
a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/AccessController.java
 
b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/AccessController.java
new file mode 100644
index 0000000..9d8ff1b
--- /dev/null
+++ 
b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/AccessController.java
@@ -0,0 +1,169 @@
+/*
+ * 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.authentication.provider;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.DynamicPropertyFactory;
+
+/**
+ * Add black / white list control to service access
+ */
+public class AccessController {
+  class ConfigurationItem {
+    static final String CATEGORY_PROPERTY = "property";
+
+    String category;
+
+    String propertyName;
+
+    String rule;
+  }
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(AccessController.class);
+
+  private static final String KEY_WHITE_LIST_PREFIX = 
"servicecomb.publicKey.accessControl.white";
+
+  private static final String KEY_BLACK_LIST_PREFIX = 
"servicecomb.publicKey.accessControl.black";
+
+  private static final String KEY_PROPERTY_NAME = "%s.%s.propertyName";
+
+  private static final String KEY_CATEGORY = "%s.%s.category";
+
+  private static final String KEY_RULE_POSTFIX = ".rule";
+
+  private Map<String, ConfigurationItem> whiteList = new HashMap<>();
+
+  private Map<String, ConfigurationItem> blackList = new HashMap<>();
+
+  public AccessController() {
+    loadConfigurations(KEY_BLACK_LIST_PREFIX);
+    loadConfigurations(KEY_WHITE_LIST_PREFIX);
+  }
+
+  public boolean isAllowed(Microservice microservice) {
+    return whiteAllowed(microservice) && !blackDenied(microservice);
+  }
+
+  private boolean whiteAllowed(Microservice microservice) {
+    if(whiteList.isEmpty()) {
+      return true;
+    }
+    return matchFound(microservice, whiteList);
+  }
+
+  private boolean blackDenied(Microservice microservice) {
+    if(blackList.isEmpty()) {
+      return false;
+    }
+    return matchFound(microservice, blackList);
+  }
+
+  private boolean matchFound(Microservice microservice, Map<String, 
ConfigurationItem> ruleList) {
+    boolean matched = false;
+    for (ConfigurationItem item : ruleList.values()) {
+      // TODO: Currently we only support property, not support tags. And we 
will support tags later.
+      if (ConfigurationItem.CATEGORY_PROPERTY.equals(item.category)) {
+        // TODO: Currently we only support to configure serviceName. And we 
will support others later.
+        if ("serviceName".equals(item.propertyName)) {
+          if (isPatternMatch(microservice.getServiceName(), item.rule)) {
+            matched = true;
+            break;
+          }
+        }
+      }
+    }
+    return matched;
+  }
+
+  private boolean isPatternMatch(String value, String pattern) {
+    if (pattern.startsWith("*")) {
+      return value.endsWith(pattern.substring(1));
+    }
+    if (pattern.endsWith("*")) {
+      return value.startsWith(pattern.substring(0, pattern.length() - 1));
+    }
+    return value.equals(pattern);
+  }
+
+  private void loadConfigurations(String prefix) {
+    ConcurrentCompositeConfiguration config = 
(ConcurrentCompositeConfiguration) DynamicPropertyFactory
+        .getBackingConfigurationSource();
+    loadConfigurations(config, prefix);
+    config.addConfigurationListener(event -> {
+      if (event.getPropertyName().startsWith(prefix)) {
+        LOG.info("Access rule have been changed. Reload configurations. 
Event=" + event.getType());
+        loadConfigurations(config, prefix);
+      }
+    });
+  }
+
+  private void loadConfigurations(ConcurrentCompositeConfiguration config, 
String prefix) {
+    Map<String, ConfigurationItem> configurations = new HashMap<>();
+    Iterator<String> configsItems = config.getKeys(prefix);
+    while (configsItems.hasNext()) {
+      String pathKey = configsItems.next();
+      if (pathKey.endsWith(KEY_RULE_POSTFIX)) {
+        ConfigurationItem configurationItem = new ConfigurationItem();
+        String rule = DynamicPropertyFactory.getInstance()
+            .getStringProperty(pathKey, null).get();
+        if (StringUtils.isEmpty(rule)) {
+          continue;
+        }
+        configurationItem.rule = rule;
+        String pathKeyItem = pathKey
+            .substring(prefix.length() + 1, pathKey.length() - 
KEY_RULE_POSTFIX.length());
+        configurationItem.propertyName = DynamicPropertyFactory.getInstance()
+            .getStringProperty(String.format(KEY_PROPERTY_NAME, prefix, 
pathKeyItem), null).get();
+        if (StringUtils.isEmpty(configurationItem.propertyName)) {
+          continue;
+        }
+        configurationItem.category = DynamicPropertyFactory.getInstance()
+            .getStringProperty(String.format(KEY_CATEGORY, prefix, 
pathKeyItem), null).get();
+        if (StringUtils.isEmpty(configurationItem.category)) {
+          continue;
+        }
+        configurations.put(pathKeyItem, configurationItem);
+      }
+    }
+
+    if (KEY_WHITE_LIST_PREFIX.equals(prefix)) {
+      this.whiteList = configurations;
+      logConfigurations(prefix, configurations, true);
+    } else {
+      this.blackList = configurations;
+      logConfigurations(prefix, configurations, false);
+    }
+  }
+
+  private void logConfigurations(String prefix, Map<String, ConfigurationItem> 
configurations, boolean isWhite) {
+    for (String key : configurations.keySet()) {
+      ConfigurationItem item = configurations.get(key);
+      LOG.info((isWhite ? "White list " : "Black list ") + "config item: key=" 
+ key + ";category=" + item.category
+          + ";propertyName=" + item.propertyName
+          + ";rule=" + item.rule);
+    }
+  }
+}
diff --git 
a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/RSAProviderTokenManager.java
 
b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/RSAProviderTokenManager.java
index 9c379a9..e0add99 100644
--- 
a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/RSAProviderTokenManager.java
+++ 
b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/RSAProviderTokenManager.java
@@ -37,6 +37,8 @@ public class RSAProviderTokenManager {
 
   private Set<RSAAuthenticationToken> validatedToken = 
ConcurrentHashMap.newKeySet(1000);
 
+  private AccessController accessController = new AccessController();
+
   public boolean valid(String token) {
     try {
       RSAAuthenticationToken rsaToken = RSAAuthenticationToken.fromStr(token);
@@ -49,7 +51,7 @@ public class RSAProviderTokenManager {
         return false;
       }
       if (validatedToken.contains(rsaToken)) {
-        return true;
+        return 
accessController.isAllowed(MicroserviceInstanceCache.getOrCreate(rsaToken.getServiceId()));
       }
 
       String sign = rsaToken.getSign();
@@ -58,10 +60,8 @@ public class RSAProviderTokenManager {
       boolean verify = RSAUtils.verify(publicKey, sign, content);
       if (verify && !tokenExprired(rsaToken)) {
         validatedToken.add(rsaToken);
-        return true;
+        return 
accessController.isAllowed(MicroserviceInstanceCache.getOrCreate(rsaToken.getServiceId()));
       }
-
-      LOGGER.error("token verify error");
       return false;
     } catch (InvalidKeyException | NoSuchAlgorithmException | 
InvalidKeySpecException | SignatureException e) {
       LOGGER.error("verfiy error", e);
diff --git 
a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAccessController.java
 
b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAccessController.java
new file mode 100644
index 0000000..c577449
--- /dev/null
+++ 
b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAccessController.java
@@ -0,0 +1,116 @@
+/*
+ * 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.authentication;
+
+import org.apache.servicecomb.authentication.provider.AccessController;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestAccessController {
+  @Before
+  public void setUp() throws Exception {
+    Log4jUtils.init();
+  }
+
+  @After
+  public void tearDown() {
+    ArchaiusUtils.resetConfig();
+  }
+
+  @Test
+  public void testIsValidOfWhite() {
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.propertyName",
 "serviceName");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.category",
 "property");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule",
 "trust*");
+    AccessController controller = new AccessController();
+    Microservice service = Mockito.mock(Microservice.class);
+
+    Mockito.when(service.getServiceName()).thenReturn("trustCustomer");
+    Assert.assertTrue(controller.isAllowed(service));
+
+    Mockito.when(service.getServiceName()).thenReturn("nottrustCustomer");
+    Assert.assertTrue(!controller.isAllowed(service));
+
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule",
 "*trust");
+    Mockito.when(service.getServiceName()).thenReturn("Customer_trust");
+    Assert.assertTrue(controller.isAllowed(service));
+
+    Mockito.when(service.getServiceName()).thenReturn("Customer_trust_not");
+    Assert.assertTrue(!controller.isAllowed(service));
+
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule",
 "trust");
+    Mockito.when(service.getServiceName()).thenReturn("trust");
+    Assert.assertTrue(controller.isAllowed(service));
+
+    Mockito.when(service.getServiceName()).thenReturn("Customer_trust");
+    Assert.assertTrue(!controller.isAllowed(service));
+  }
+
+  @Test
+  public void testIsValidOfBlack() {
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.propertyName",
 "serviceName");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.category",
 "property");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule",
 "trust*");
+    AccessController controller = new AccessController();
+    Microservice service = Mockito.mock(Microservice.class);
+
+    Mockito.when(service.getServiceName()).thenReturn("trustCustomer");
+    Assert.assertTrue(!controller.isAllowed(service));
+
+    Mockito.when(service.getServiceName()).thenReturn("nottrustCustomer");
+    Assert.assertTrue(controller.isAllowed(service));
+
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule",
 "*trust");
+    Mockito.when(service.getServiceName()).thenReturn("Customer_trust");
+    Assert.assertTrue(!controller.isAllowed(service));
+
+    Mockito.when(service.getServiceName()).thenReturn("Customer_trust_not");
+    Assert.assertTrue(controller.isAllowed(service));
+
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule",
 "trust");
+    Mockito.when(service.getServiceName()).thenReturn("trust");
+    Assert.assertTrue(!controller.isAllowed(service));
+
+    Mockito.when(service.getServiceName()).thenReturn("Customer_trust");
+    Assert.assertTrue(controller.isAllowed(service));
+  }
+
+  @Test
+  public void testIsValidOfBlackAndWhite() {
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.propertyName",
 "serviceName");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.category",
 "property");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule",
 "trust*");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.propertyName",
 "serviceName");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.category",
 "property");
+    
ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule",
 "*hacker");
+
+    AccessController controller = new AccessController();
+    Microservice service = Mockito.mock(Microservice.class);
+
+    Mockito.when(service.getServiceName()).thenReturn("trustCustomer");
+    Assert.assertTrue(controller.isAllowed(service));
+
+    Mockito.when(service.getServiceName()).thenReturn("trustCustomerhacker");
+    Assert.assertTrue(!controller.isAllowed(service));
+  }
+}
diff --git 
a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestProviderAuthHanlder.java
 
b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestProviderAuthHanlder.java
index 2c18417..27b496a 100644
--- 
a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestProviderAuthHanlder.java
+++ 
b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestProviderAuthHanlder.java
@@ -17,9 +17,12 @@
 package org.apache.servicecomb.authentication;
 
 import org.apache.servicecomb.authentication.provider.ProviderAuthHanlder;
+import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -32,11 +35,15 @@ public class TestProviderAuthHanlder {
 
   @Before
   public void setUp() throws Exception {
+    ConfigUtil.installDynamicConfig();
     invocation = Mockito.mock(Invocation.class);
     asyncResp = Mockito.mock(AsyncResponse.class);
     
Mockito.when(invocation.getContext(Const.AUTH_TOKEN)).thenReturn("testtoken");
   }
-
+  @After
+  public void tearDown() {
+    ArchaiusUtils.resetConfig();
+  }
   @Test
   public void testHandle() throws Exception {
     ProviderAuthHanlder providerAuthHanlder = new ProviderAuthHanlder();
diff --git 
a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAProviderTokenManager.java
 
b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAProviderTokenManager.java
index eb47d1b..6efbaf9 100644
--- 
a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAProviderTokenManager.java
+++ 
b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAProviderTokenManager.java
@@ -21,15 +21,19 @@ import java.util.Map;
 
 import org.apache.servicecomb.authentication.consumer.RSAConsumerTokenManager;
 import org.apache.servicecomb.authentication.provider.RSAProviderTokenManager;
+import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.foundation.common.utils.RSAKeyPairEntry;
 import org.apache.servicecomb.foundation.common.utils.RSAUtils;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.apache.servicecomb.foundation.token.RSAKeypair4Auth;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.serviceregistry.api.Const;
 import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
 import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.serviceregistry.cache.MicroserviceInstanceCache;
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import mockit.Expectations;
@@ -37,6 +41,16 @@ import mockit.Expectations;
 public class TestRSAProviderTokenManager {
 
 
+  @Before
+  public void setUp() throws Exception {
+    ConfigUtil.installDynamicConfig();
+  }
+
+  @After
+  public void tearDown() {
+    ArchaiusUtils.resetConfig();
+  }
+
   @Test
   public void testTokenExpried() {
     String tokenStr =
@@ -84,6 +98,8 @@ public class TestRSAProviderTokenManager {
       {
         MicroserviceInstanceCache.getOrCreate(serviceId, instanceId);
         result = microserviceInstance;
+        MicroserviceInstanceCache.getOrCreate(serviceId);
+        result = microservice;
       }
     };
     RSAProviderTokenManager rsaProviderTokenManager = new 
RSAProviderTokenManager();
diff --git a/samples/pom.xml b/samples/pom.xml
index 4acbd03..d706af0 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -38,6 +38,7 @@
     <module>metrics-extend-healthcheck</module>
     <module>config-apollo-sample</module>
     <module>use-log4j2-sample</module>
+    <module>trust-sample</module>
   </modules>
 
   <dependencyManagement>
diff --git a/samples/trust-sample/README.md b/samples/trust-sample/README.md
new file mode 100644
index 0000000..e3a0694
--- /dev/null
+++ b/samples/trust-sample/README.md
@@ -0,0 +1,4 @@
+## Trust Sample
+This sample shows using public key mechanism to authenticate user and 
black/white user list. The public key mechanism security is based on Service 
Center, and users should first configure Service Center authentication. This 
sample does not show how to configure Service Center authentication.
+
+In this sample, both customer and hacker try to access store, while store 
configure it's black list to deny hacker's access.
\ No newline at end of file
diff --git a/handlers/handler-publickey-auth/pom.xml 
b/samples/trust-sample/customer/pom.xml
similarity index 58%
copy from handlers/handler-publickey-auth/pom.xml
copy to samples/trust-sample/customer/pom.xml
index 9fd5019..8aa3839 100644
--- a/handlers/handler-publickey-auth/pom.xml
+++ b/samples/trust-sample/customer/pom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements.  See the NOTICE file distributed with
@@ -14,39 +15,47 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
 <project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
   <modelVersion>4.0.0</modelVersion>
   <parent>
-    <groupId>org.apache.servicecomb</groupId>
-    <artifactId>handlers</artifactId>
+    <groupId>org.apache.servicecomb.samples</groupId>
+    <artifactId>trust-sample</artifactId>
     <version>1.0.0-m2-SNAPSHOT</version>
   </parent>
-
-  <artifactId>handler-publickey-auth</artifactId>
-  <name>Java Chassis::Handlers::PublicKey Auth</name>
-
-  <properties>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-  </properties>
-
+  <artifactId>customer</artifactId>
   <dependencies>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
-      <artifactId>java-chassis-core</artifactId>
+      <artifactId>handler-publickey-auth</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-loadbalance</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-highway</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-rest-vertx</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-flowcontrol-qps</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-pojo</artifactId>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>log4j</artifactId>
-      <scope>test</scope>
+      <groupId>org.apache.servicecomb.samples</groupId>
+      <artifactId>common-schema</artifactId>
     </dependency>
-
   </dependencies>
-
 </project>
diff --git 
a/samples/trust-sample/customer/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
 
b/samples/trust-sample/customer/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
new file mode 100644
index 0000000..b9557b2
--- /dev/null
+++ 
b/samples/trust-sample/customer/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
@@ -0,0 +1,28 @@
+/*
+ * 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.samples.trust;
+
+public interface Compute {
+
+  int add(int a, int b);
+
+  int multi(int a, int b);
+
+  int sub(int a, int b);
+
+  int divide(int a, int b);
+}
diff --git 
a/samples/trust-sample/customer/src/main/java/org/apache/servicecomb/samples/trust/consumer/CustomerMain.java
 
b/samples/trust-sample/customer/src/main/java/org/apache/servicecomb/samples/trust/consumer/CustomerMain.java
new file mode 100644
index 0000000..5c27744
--- /dev/null
+++ 
b/samples/trust-sample/customer/src/main/java/org/apache/servicecomb/samples/trust/consumer/CustomerMain.java
@@ -0,0 +1,42 @@
+/*
+ * 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.samples.trust.consumer;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.samples.trust.Compute;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CustomerMain {
+
+  @RpcReference(microserviceName = "store", schemaId = "codeFirstCompute")
+  public static Compute compute;
+
+  public static void main(String[] args)
+      throws Exception {
+    init();
+    System.out.println("a=1, b=2, result=" + compute.add(1, 2));
+  }
+
+  public static void init()
+      throws Exception {
+    Log4jUtils.init();
+    BeanUtils.init();
+  }
+}
diff --git 
a/samples/trust-sample/customer/src/main/resources/config/log4j.demo.properties 
b/samples/trust-sample/customer/src/main/resources/config/log4j.demo.properties
new file mode 100644
index 0000000..e7a487d
--- /dev/null
+++ 
b/samples/trust-sample/customer/src/main/resources/config/log4j.demo.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+paas.logs.dir=target/logs/
+paas.logs.file=sample.log
+
+log4j.rootLogger=INFO,paas,stdout
diff --git a/samples/trust-sample/customer/src/main/resources/microservice.yaml 
b/samples/trust-sample/customer/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..c96ce38
--- /dev/null
+++ b/samples/trust-sample/customer/src/main/resources/microservice.yaml
@@ -0,0 +1,37 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+APPLICATION_ID: trust-sample
+service_description:
+  name: customer
+  version: 0.0.1
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  isolation:
+    Consumer:
+      enabled: false
+  references:
+    hello:
+      version-rule: 0.0.1
+  handler:
+    chain:
+      Consumer:
+        default: loadbalance,auth-consumer
+      Provider:
+        default: auth-provider
diff --git a/handlers/handler-publickey-auth/pom.xml 
b/samples/trust-sample/hacker/pom.xml
similarity index 55%
copy from handlers/handler-publickey-auth/pom.xml
copy to samples/trust-sample/hacker/pom.xml
index 9fd5019..91c7a31 100644
--- a/handlers/handler-publickey-auth/pom.xml
+++ b/samples/trust-sample/hacker/pom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements.  See the NOTICE file distributed with
@@ -14,39 +15,51 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
 <project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
   <modelVersion>4.0.0</modelVersion>
   <parent>
-    <groupId>org.apache.servicecomb</groupId>
-    <artifactId>handlers</artifactId>
+    <groupId>org.apache.servicecomb.samples</groupId>
+    <artifactId>trust-sample</artifactId>
     <version>1.0.0-m2-SNAPSHOT</version>
   </parent>
-
-  <artifactId>handler-publickey-auth</artifactId>
-  <name>Java Chassis::Handlers::PublicKey Auth</name>
-
-  <properties>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-  </properties>
-
+  <artifactId>hacker</artifactId>
   <dependencies>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
-      <artifactId>java-chassis-core</artifactId>
+      <artifactId>handler-bizkeeper</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-publickey-auth</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-loadbalance</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-highway</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-rest-vertx</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-flowcontrol-qps</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-pojo</artifactId>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>log4j</artifactId>
-      <scope>test</scope>
+      <groupId>org.apache.servicecomb.samples</groupId>
+      <artifactId>common-schema</artifactId>
     </dependency>
-
   </dependencies>
-
 </project>
diff --git 
a/samples/trust-sample/hacker/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
 
b/samples/trust-sample/hacker/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
new file mode 100644
index 0000000..b9557b2
--- /dev/null
+++ 
b/samples/trust-sample/hacker/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
@@ -0,0 +1,28 @@
+/*
+ * 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.samples.trust;
+
+public interface Compute {
+
+  int add(int a, int b);
+
+  int multi(int a, int b);
+
+  int sub(int a, int b);
+
+  int divide(int a, int b);
+}
diff --git 
a/samples/trust-sample/hacker/src/main/java/org/apache/servicecomb/samples/trust/consumer/HackerMain.java
 
b/samples/trust-sample/hacker/src/main/java/org/apache/servicecomb/samples/trust/consumer/HackerMain.java
new file mode 100644
index 0000000..6477319
--- /dev/null
+++ 
b/samples/trust-sample/hacker/src/main/java/org/apache/servicecomb/samples/trust/consumer/HackerMain.java
@@ -0,0 +1,41 @@
+/*
+ * 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.samples.trust.consumer;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.samples.trust.Compute;
+import org.springframework.stereotype.Component;
+
+@Component
+public class HackerMain {
+  @RpcReference(microserviceName = "store", schemaId = "codeFirstCompute")
+  public static Compute compute;
+
+  public static void main(String[] args)
+      throws Exception {
+    init();
+    System.out.println("a=1, b=2, result=" + compute.add(1, 2));
+  }
+
+  public static void init()
+      throws Exception {
+    Log4jUtils.init();
+    BeanUtils.init();
+  }
+}
diff --git 
a/samples/trust-sample/hacker/src/main/resources/config/log4j.demo.properties 
b/samples/trust-sample/hacker/src/main/resources/config/log4j.demo.properties
new file mode 100644
index 0000000..e7a487d
--- /dev/null
+++ 
b/samples/trust-sample/hacker/src/main/resources/config/log4j.demo.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+paas.logs.dir=target/logs/
+paas.logs.file=sample.log
+
+log4j.rootLogger=INFO,paas,stdout
diff --git a/samples/trust-sample/hacker/src/main/resources/microservice.yaml 
b/samples/trust-sample/hacker/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..ec33b21
--- /dev/null
+++ b/samples/trust-sample/hacker/src/main/resources/microservice.yaml
@@ -0,0 +1,37 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+APPLICATION_ID: trust-sample
+service_description:
+  name: hacker
+  version: 0.0.1
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  isolation:
+    Consumer:
+      enabled: false
+  references:
+    hello:
+      version-rule: 0.0.1
+  handler:
+    chain:
+      Consumer:
+        default: loadbalance,auth-consumer
+      Provider:
+        default: auth-provider
diff --git a/handlers/handler-publickey-auth/pom.xml 
b/samples/trust-sample/pom.xml
similarity index 60%
copy from handlers/handler-publickey-auth/pom.xml
copy to samples/trust-sample/pom.xml
index 9fd5019..d688a54 100644
--- a/handlers/handler-publickey-auth/pom.xml
+++ b/samples/trust-sample/pom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements.  See the NOTICE file distributed with
@@ -14,39 +15,19 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
 <project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
   <modelVersion>4.0.0</modelVersion>
   <parent>
-    <groupId>org.apache.servicecomb</groupId>
-    <artifactId>handlers</artifactId>
+    <groupId>org.apache.servicecomb.samples</groupId>
+    <artifactId>samples</artifactId>
     <version>1.0.0-m2-SNAPSHOT</version>
   </parent>
-
-  <artifactId>handler-publickey-auth</artifactId>
-  <name>Java Chassis::Handlers::PublicKey Auth</name>
-
-  <properties>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.servicecomb</groupId>
-      <artifactId>java-chassis-core</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>log4j</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-  </dependencies>
-
+  <artifactId>trust-sample</artifactId>
+  <packaging>pom</packaging>
+  <modules>
+    <module>store</module>
+    <module>customer</module>
+    <module>hacker</module>
+  </modules>
 </project>
diff --git a/handlers/handler-publickey-auth/pom.xml 
b/samples/trust-sample/store/pom.xml
similarity index 55%
copy from handlers/handler-publickey-auth/pom.xml
copy to samples/trust-sample/store/pom.xml
index 9fd5019..07e9893 100644
--- a/handlers/handler-publickey-auth/pom.xml
+++ b/samples/trust-sample/store/pom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements.  See the NOTICE file distributed with
@@ -14,39 +15,51 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
 <project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
   <modelVersion>4.0.0</modelVersion>
   <parent>
-    <groupId>org.apache.servicecomb</groupId>
-    <artifactId>handlers</artifactId>
+    <groupId>org.apache.servicecomb.samples</groupId>
+    <artifactId>trust-sample</artifactId>
     <version>1.0.0-m2-SNAPSHOT</version>
   </parent>
-
-  <artifactId>handler-publickey-auth</artifactId>
-  <name>Java Chassis::Handlers::PublicKey Auth</name>
-
-  <properties>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-  </properties>
-
+  <artifactId>store</artifactId>
   <dependencies>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
-      <artifactId>java-chassis-core</artifactId>
+      <artifactId>handler-bizkeeper</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-publickey-auth</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-loadbalance</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-highway</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-rest-vertx</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-flowcontrol-qps</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-pojo</artifactId>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>log4j</artifactId>
-      <scope>test</scope>
+      <groupId>org.apache.servicecomb.samples</groupId>
+      <artifactId>common-schema</artifactId>
     </dependency>
-
   </dependencies>
-
 </project>
diff --git 
a/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
 
b/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
new file mode 100644
index 0000000..b9557b2
--- /dev/null
+++ 
b/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/Compute.java
@@ -0,0 +1,28 @@
+/*
+ * 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.samples.trust;
+
+public interface Compute {
+
+  int add(int a, int b);
+
+  int multi(int a, int b);
+
+  int sub(int a, int b);
+
+  int divide(int a, int b);
+}
diff --git 
a/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/provider/CodeFirstComputeImpl.java
 
b/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/provider/CodeFirstComputeImpl.java
new file mode 100644
index 0000000..9c21237
--- /dev/null
+++ 
b/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/provider/CodeFirstComputeImpl.java
@@ -0,0 +1,48 @@
+/*
+ * 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.samples.trust.provider;
+
+
+import org.apache.servicecomb.provider.pojo.RpcSchema;
+import org.apache.servicecomb.samples.trust.Compute;
+
+@RpcSchema(schemaId = "codeFirstCompute")
+public class CodeFirstComputeImpl implements Compute {
+  @Override
+  public int add(int a, int b) {
+    return a + b;
+  }
+
+  @Override
+  public int multi(int a, int b) {
+    return a * b;
+  }
+
+  @Override
+  public int sub(int a, int b) {
+    return a - b;
+  }
+
+  @Override
+  public int divide(int a, int b) {
+    if (b != 0) {
+      return a / b;
+    }
+    return 0;
+  }
+}
diff --git 
a/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/provider/TrustMain.java
 
b/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/provider/TrustMain.java
new file mode 100644
index 0000000..fcab51b
--- /dev/null
+++ 
b/samples/trust-sample/store/src/main/java/org/apache/servicecomb/samples/trust/provider/TrustMain.java
@@ -0,0 +1,29 @@
+/*
+ * 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.samples.trust.provider;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+
+public class TrustMain {
+
+  public static void main(String[] args) throws Exception {
+    Log4jUtils.init();
+    BeanUtils.init();
+  }
+}
diff --git 
a/samples/trust-sample/store/src/main/resources/config/log4j.demo.properties 
b/samples/trust-sample/store/src/main/resources/config/log4j.demo.properties
new file mode 100644
index 0000000..e7a487d
--- /dev/null
+++ b/samples/trust-sample/store/src/main/resources/config/log4j.demo.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+paas.logs.dir=target/logs/
+paas.logs.file=sample.log
+
+log4j.rootLogger=INFO,paas,stdout
diff --git a/samples/trust-sample/store/src/main/resources/microservice.yaml 
b/samples/trust-sample/store/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..88bf72b
--- /dev/null
+++ b/samples/trust-sample/store/src/main/resources/microservice.yaml
@@ -0,0 +1,47 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+APPLICATION_ID: trust-sample
+service_description:
+  name: store
+  version: 0.0.1
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  rest:
+    address: 0.0.0.0:8080
+  highway:
+    address: 0.0.0.0:7070
+  handler:
+    chain:
+      Consumer:
+        default: loadbalance,auth-consumer
+      Provider:
+        default: auth-provider
+  publicKey:
+    accessControl:
+      black:
+        list01:
+          category: property ## property, fixed value
+          propertyName: serviceName ## property name
+          rule: hacker ## property value match expression. only supports 
prefix match and postfix match and exactly match. e.g. hacker*, *hacker, hacker
+      white:
+        list02:
+          category: property
+          propertyName: serviceName
+          rule: cust*
\ No newline at end of file
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/MicroserviceInstanceCache.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/MicroserviceInstanceCache.java
index 2e67d4a..eb6828d 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/MicroserviceInstanceCache.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/MicroserviceInstanceCache.java
@@ -22,12 +22,14 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
 import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
+import com.google.common.util.concurrent.UncheckedExecutionException;
 
 /**
  * 微服务实例缓存 key为:serviceId@instanceId 缓存limit:1000 缓存老化策略:30分钟没有访问就过期。
@@ -42,6 +44,26 @@ public class MicroserviceInstanceCache {
       .expireAfterAccess(30, TimeUnit.MINUTES)
       .build();
 
+  private static final Cache<String, Microservice> microservices = 
CacheBuilder.newBuilder()
+      .maximumSize(1000)
+      .expireAfterAccess(30, TimeUnit.MINUTES)
+      .build();
+
+  public static Microservice getOrCreate(String serviceId) {
+    try {
+      return microservices.get(serviceId, () -> {
+        Microservice microservice = 
RegistryUtils.getServiceRegistryClient().getMicroservice(serviceId);
+        if (microservice == null) {
+          throw new IllegalArgumentException("service id not exists.");
+        }
+        return microservice;
+      });
+    } catch (ExecutionException | UncheckedExecutionException e) {
+      logger.error("get microservice from cache failed, {}, {}", serviceId, 
e.getMessage());
+      return null;
+    }
+  }
+
   public static MicroserviceInstance getOrCreate(String serviceId, String 
instanceId) {
     try {
       String key = String.format("%s@%s", serviceId, instanceId);
@@ -49,17 +71,18 @@ public class MicroserviceInstanceCache {
 
         @Override
         public MicroserviceInstance call() throws Exception {
-          logger.debug("get microservice instance from SC");
-          return getMicroserviceInstanceFromSC(serviceId, instanceId);
+          MicroserviceInstance instance = 
RegistryUtils.getServiceRegistryClient()
+              .findServiceInstance(serviceId, instanceId);
+          if (instance == null) {
+            throw new IllegalArgumentException("instance id not exists.");
+          }
+          return instance;
         }
       });
-    } catch (ExecutionException e) {
-      logger.error("get microservice from cache failed:" + 
String.format("%s@%s", serviceId, instanceId));
+    } catch (ExecutionException | UncheckedExecutionException e) {
+      logger.error("get microservice instance from cache failed, {}, {}", 
String.format("%s@%s", serviceId, instanceId),
+          e.getMessage());
       return null;
     }
   }
-
-  private static MicroserviceInstance getMicroserviceInstanceFromSC(String 
serviceId, String instanceId) {
-    return 
RegistryUtils.getServiceRegistryClient().findServiceInstance(serviceId, 
instanceId);
-  }
 }
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/cache/TestMicroserviceInstanceCache.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/cache/TestMicroserviceInstanceCache.java
new file mode 100644
index 0000000..5e55e6d
--- /dev/null
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/cache/TestMicroserviceInstanceCache.java
@@ -0,0 +1,72 @@
+/*
+ * 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.serviceregistry.cache;
+
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.client.ServiceRegistryClient;
+import org.junit.Assert;
+import org.junit.Test;
+
+import mockit.Expectations;
+import mockit.Mocked;
+
+public class TestMicroserviceInstanceCache {
+  @Test
+  public void testGetOrCreateMicroservice(@Mocked RegistryUtils utils, @Mocked 
ServiceRegistryClient client,
+      @Mocked Microservice microservice) {
+    new Expectations() {
+      {
+        RegistryUtils.getServiceRegistryClient();
+        result = client;
+        client.getMicroservice("forkedid");
+        result = microservice;
+        client.getMicroservice("forkedidNull");
+        result = null;
+      }
+    };
+    Microservice cachedService = 
MicroserviceInstanceCache.getOrCreate("forkedid");
+    Assert.assertNotNull(cachedService);
+    cachedService = MicroserviceInstanceCache.getOrCreate("forkedid");
+    Assert.assertNotNull(cachedService);
+    cachedService = MicroserviceInstanceCache.getOrCreate("forkedidNull");
+    Assert.assertNull(cachedService);
+  }
+
+  @Test
+  public void testGetOrCreateMicroserviceInstance(@Mocked RegistryUtils utils, 
@Mocked ServiceRegistryClient client,
+      @Mocked MicroserviceInstance instance) {
+    new Expectations() {
+      {
+        RegistryUtils.getServiceRegistryClient();
+        result = client;
+        client.findServiceInstance("forkedserviceid", "forkedinstanceid");
+        result = instance;
+        client.findServiceInstance("forkedserviceidNull", 
"forkedinstanceidNull");
+        result = null;
+      }
+    };
+    MicroserviceInstance cachedInstance = 
MicroserviceInstanceCache.getOrCreate("forkedserviceid", "forkedinstanceid");
+    Assert.assertNotNull(cachedInstance);
+    cachedInstance = MicroserviceInstanceCache.getOrCreate("forkedserviceid", 
"forkedinstanceid");
+    Assert.assertNotNull(cachedInstance);
+    cachedInstance = 
MicroserviceInstanceCache.getOrCreate("forkedserviceidNull", 
"forkedinstanceidNull");
+    Assert.assertNull(cachedInstance);
+  }
+}

Reply via email to