diff --git a/README.md b/README.md
index 36e0ad78c3aefe21c3847f2ede1c4cbec8db9851..c5ad2f3a568b1cbd3e11cd37633922a27ffefa3f 100644
--- a/README.md
+++ b/README.md
@@ -34,13 +34,13 @@ Finished List:
 - Configure Center: Zookeeper
 - Cluster Strategy: Failover/[Failfast](https://github.com/apache/dubbo-go/pull/140)/[Failsafe/Failback](https://github.com/apache/dubbo-go/pull/136)/[Available](https://github.com/apache/dubbo-go/pull/155)/[Broadcast](https://github.com/apache/dubbo-go/pull/158)/[Forking](https://github.com/apache/dubbo-go/pull/161)
 - Load Balance: Random/[RoundRobin](https://github.com/apache/dubbo-go/pull/66)/[LeastActive](https://github.com/apache/dubbo-go/pull/65)
-- Filter: Echo Health Check/[Circuit break and service downgrade](https://github.com/apache/dubbo-go/pull/133)
+- Filter: Echo Health Check/[Circuit break and service downgrade](https://github.com/apache/dubbo-go/pull/133)/[TokenFilter](https://github.com/apache/dubbo-go/pull/202)
 - Other feature: [generic invoke](https://github.com/apache/dubbo-go/pull/122)/start check/connecting certain provider/multi-protocols/multi-registries/multi-versions/service group
 
 Working List:
 
 - Load Balance: ConsistentHash
-- Filter: TokenFilter/AccessLogFilter/CountFilter/ExecuteLimitFilter/TpsLimitFilter
+- Filter: AccessLogFilter/CountFilter/ExecuteLimitFilter/TpsLimitFilter
 - Registry: k8s
 - Configure Center: apollo
 - Dynamic Configuration Center & Metadata Center (dubbo v2.7.x)
diff --git a/README_CN.md b/README_CN.md
index 387070d267fbba05fb99226f83bde45e236e491c..266d1d0e9216446d60087556a67680b831aa143a 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -33,14 +33,14 @@ Apache License, Version 2.0
 - 閰嶇疆涓績: Zookeeper
 - 闆嗙兢绛栫暐: Failover/[Failfast](https://github.com/apache/dubbo-go/pull/140)/[Failsafe/Failback](https://github.com/apache/dubbo-go/pull/136)/[Available](https://github.com/apache/dubbo-go/pull/155)/[Broadcast](https://github.com/apache/dubbo-go/pull/158)/[Forking](https://github.com/apache/dubbo-go/pull/161)
 - 璐熻浇鍧囪 绛栫暐: Random/[RoundRobin](https://github.com/apache/dubbo-go/pull/66)/[LeastActive](https://github.com/apache/dubbo-go/pull/65)
-- 杩囨护鍣�: Echo Health Check/[鏈嶅姟鐔旀柇&闄嶇骇](https://github.com/apache/dubbo-go/pull/133)
+- 杩囨护鍣�: Echo Health Check/[鏈嶅姟鐔旀柇&闄嶇骇](https://github.com/apache/dubbo-go/pull/133)/[TokenFilter](https://github.com/apache/dubbo-go/pull/202)
 - 鍏朵粬鍔熻兘鏀寔: [娉涘寲璋冪敤](https://github.com/apache/dubbo-go/pull/122)/鍚姩鏃舵鏌�/鏈嶅姟鐩磋繛/澶氭湇鍔″崗璁�/澶氭敞鍐屼腑蹇�/澶氭湇鍔$増鏈�/鏈嶅姟鍒嗙粍
 
 寮€鍙戜腑鍒楄〃:
 
 - 闆嗙兢绛栫暐: Forking
 - 璐熻浇鍧囪 绛栫暐: ConsistentHash
-- 杩囨护鍣�: TokenFilter/AccessLogFilter/CountFilter/ExecuteLimitFilter/TpsLimitFilter
+- 杩囨护鍣�: AccessLogFilter/CountFilter/ExecuteLimitFilter/TpsLimitFilter
 - 娉ㄥ唽涓績: k8s
 - 閰嶇疆涓績: apollo
 - 鍔ㄦ€侀厤缃腑蹇� & 鍏冩暟鎹腑蹇� (dubbo v2.7.x)
diff --git a/common/constant/default.go b/common/constant/default.go
index d937fcb3edb5075922655db8824c9ca2ede5ce1c..405920e20f4afadddf88b26e3fc169c149a9f2e6 100644
--- a/common/constant/default.go
+++ b/common/constant/default.go
@@ -46,7 +46,7 @@ const (
 const (
 	DEFAULT_KEY               = "default"
 	PREFIX_DEFAULT_KEY        = "default."
-	DEFAULT_SERVICE_FILTERS   = "echo"
+	DEFAULT_SERVICE_FILTERS   = "echo,token"
 	DEFAULT_REFERENCE_FILTERS = ""
 	GENERIC_REFERENCE_FILTERS = "generic"
 	GENERIC                   = "$invoke"
diff --git a/common/constant/key.go b/common/constant/key.go
index 1b25d11edc6cb2c416d017e508169461f9b2c569..abb78c987b44f827cea93150df0848a7d1557dec 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -37,6 +37,7 @@ const (
 	BEAN_NAME_KEY          = "bean.name"
 	GENERIC_KEY            = "generic"
 	CLASSIFIER_KEY         = "classifier"
+	TOKEN_KEY              = "token"
 )
 
 const (
diff --git a/common/url.go b/common/url.go
index 9f5b50264afe5f60feff2bbccee6cb894aaa44f3..bf58ca188c1769b81ed475f06852d0f4229ab97d 100644
--- a/common/url.go
+++ b/common/url.go
@@ -34,6 +34,7 @@ import (
 	"github.com/dubbogo/gost/container"
 	"github.com/jinzhu/copier"
 	perrors "github.com/pkg/errors"
+	"github.com/satori/go.uuid"
 )
 
 import (
@@ -150,6 +151,18 @@ func WithLocation(location string) option {
 	}
 }
 
+func WithToken(token string) option {
+	return func(url *URL) {
+		if len(token) > 0 {
+			value := token
+			if strings.ToLower(token) == "true" || strings.ToLower(token) == "default" {
+				value = uuid.NewV4().String()
+			}
+			url.SetParam(constant.TOKEN_KEY, value)
+		}
+	}
+}
+
 func NewURLWithOptions(opts ...option) *URL {
 	url := &URL{}
 	for _, opt := range opts {
diff --git a/config/service_config.go b/config/service_config.go
index df6b8d183907a79768f855c2e33bc888a19fa9e3..ce15c61eb3ce9c1bf64f629df3d2c52e300d1a2c 100644
--- a/config/service_config.go
+++ b/config/service_config.go
@@ -57,6 +57,7 @@ type ServiceConfig struct {
 	Warmup        string            `yaml:"warmup"  json:"warmup,omitempty"  property:"warmup"`
 	Retries       string            `yaml:"retries"  json:"retries,omitempty" property:"retries"`
 	Params        map[string]string `yaml:"params"  json:"params,omitempty" property:"params"`
+	Token         string            `yaml:"token" json:"token,omitempty" property:"token"`
 	unexported    *atomic.Bool
 	exported      *atomic.Bool
 	rpcService    common.RPCService
@@ -122,7 +123,10 @@ func (srvconfig *ServiceConfig) Export() error {
 			common.WithPort(proto.Port),
 			common.WithParams(urlMap),
 			common.WithParamsValue(constant.BEAN_NAME_KEY, srvconfig.id),
-			common.WithMethods(strings.Split(methods, ",")))
+			common.WithMethods(strings.Split(methods, ",")),
+			common.WithToken(srvconfig.Token),
+		)
+
 		if len(regUrls) > 0 {
 			for _, regUrl := range regUrls {
 				regUrl.SubURL = url
diff --git a/examples/helloworld/dubbo/go-server/profiles/dev/server.yml b/examples/helloworld/dubbo/go-server/profiles/dev/server.yml
index 27e9d55c8dd7f50320f90a38ac6b501425d5ba83..8e8594a1ce478b36d48b09e65ab63506b31a2c3c 100644
--- a/examples/helloworld/dubbo/go-server/profiles/dev/server.yml
+++ b/examples/helloworld/dubbo/go-server/profiles/dev/server.yml
@@ -30,6 +30,7 @@ services:
     - name: "GetUser"
       retries: "1"
       loadbalance: "random"
+    token: "true"
 
 protocols:
   "dubbo":
diff --git a/filter/impl/token_filter.go b/filter/impl/token_filter.go
new file mode 100644
index 0000000000000000000000000000000000000000..d10dff5b761d0fbe40ff3a14a93ee8962d000e02
--- /dev/null
+++ b/filter/impl/token_filter.go
@@ -0,0 +1,66 @@
+/*
+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 impl
+
+import (
+	"strings"
+)
+
+import (
+	perrors "github.com/pkg/errors"
+)
+
+import (
+	"github.com/apache/dubbo-go/common/constant"
+	"github.com/apache/dubbo-go/common/extension"
+	"github.com/apache/dubbo-go/filter"
+	"github.com/apache/dubbo-go/protocol"
+)
+
+const (
+	TOKEN = "token"
+)
+
+func init() {
+	extension.SetFilter(TOKEN, GetTokenFilter)
+}
+
+type TokenFilter struct{}
+
+func (tf *TokenFilter) Invoke(invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+	invokerTkn := invoker.GetUrl().GetParam(constant.TOKEN_KEY, "")
+	if len(invokerTkn) > 0 {
+		attachs := invocation.Attachments()
+		remoteTkn, exist := attachs[constant.TOKEN_KEY]
+		if exist && strings.EqualFold(invokerTkn, remoteTkn) {
+			return invoker.Invoke(invocation)
+		}
+		return &protocol.RPCResult{Err: perrors.Errorf("Invalid token! Forbid invoke remote service %v method %s ",
+			invoker, invocation.MethodName())}
+	}
+
+	return invoker.Invoke(invocation)
+}
+
+func (tf *TokenFilter) OnResponse(result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+	return result
+}
+
+func GetTokenFilter() filter.Filter {
+	return &TokenFilter{}
+}
diff --git a/filter/impl/token_filter_test.go b/filter/impl/token_filter_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..1473f274037699260725ff9ebb1b3d1377efb326
--- /dev/null
+++ b/filter/impl/token_filter_test.go
@@ -0,0 +1,85 @@
+/*
+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 impl
+
+import (
+	"net/url"
+	"testing"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"github.com/apache/dubbo-go/common"
+	"github.com/apache/dubbo-go/common/constant"
+	"github.com/apache/dubbo-go/protocol"
+	"github.com/apache/dubbo-go/protocol/invocation"
+)
+
+func TestTokenFilter_Invoke(t *testing.T) {
+	filter := GetTokenFilter()
+
+	url := common.NewURLWithOptions(
+		common.WithParams(url.Values{}),
+		common.WithParamsValue(constant.TOKEN_KEY, "ori_key"))
+	attch := make(map[string]string, 0)
+	attch[constant.TOKEN_KEY] = "ori_key"
+	result := filter.Invoke(protocol.NewBaseInvoker(*url),
+		invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
+	assert.Nil(t, result.Error())
+	assert.Nil(t, result.Result())
+}
+
+func TestTokenFilter_InvokeEmptyToken(t *testing.T) {
+	filter := GetTokenFilter()
+
+	url := common.URL{}
+	attch := make(map[string]string, 0)
+	attch[constant.TOKEN_KEY] = "ori_key"
+	result := filter.Invoke(protocol.NewBaseInvoker(url),
+		invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
+	assert.Nil(t, result.Error())
+	assert.Nil(t, result.Result())
+}
+
+func TestTokenFilter_InvokeEmptyAttach(t *testing.T) {
+	filter := GetTokenFilter()
+
+	url := common.NewURLWithOptions(
+		common.WithParams(url.Values{}),
+		common.WithParamsValue(constant.TOKEN_KEY, "ori_key"))
+	attch := make(map[string]string, 0)
+	result := filter.Invoke(protocol.NewBaseInvoker(*url),
+		invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
+	assert.NotNil(t, result.Error())
+}
+
+func TestTokenFilter_InvokeNotEqual(t *testing.T) {
+	filter := GetTokenFilter()
+
+	url := common.NewURLWithOptions(
+		common.WithParams(url.Values{}),
+		common.WithParamsValue(constant.TOKEN_KEY, "ori_key"))
+	attch := make(map[string]string, 0)
+	attch[constant.TOKEN_KEY] = "err_key"
+	result := filter.Invoke(protocol.NewBaseInvoker(*url),
+		invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
+	assert.NotNil(t, result.Error())
+}
diff --git a/go.mod b/go.mod
index ec3c24c278712e7aaf80638b67971bf6f2ced516..09948c93c582feca5a3c8ee8df379e03bb6a4e84 100644
--- a/go.mod
+++ b/go.mod
@@ -35,6 +35,7 @@ require (
 	github.com/pkg/errors v0.8.1
 	github.com/prometheus/client_golang v1.1.0 // indirect
 	github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec
+	github.com/satori/go.uuid v1.2.0
 	github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 // indirect
 	github.com/soheilhy/cmux v0.1.4 // indirect
 	github.com/stretchr/testify v1.3.0
diff --git a/protocol/dubbo/dubbo_invoker.go b/protocol/dubbo/dubbo_invoker.go
index 4bfc1324cf9dcdb2412e7026214f6a3951a9c7c1..bc321a97a4271c147d9317145d9f1aa76ca27902 100644
--- a/protocol/dubbo/dubbo_invoker.go
+++ b/protocol/dubbo/dubbo_invoker.go
@@ -36,6 +36,10 @@ import (
 
 var Err_No_Reply = perrors.New("request need @response")
 
+var (
+	attachmentKey = []string{constant.INTERFACE_KEY, constant.GROUP_KEY, constant.TOKEN_KEY, constant.TIMEOUT_KEY}
+)
+
 type DubboInvoker struct {
 	protocol.BaseInvoker
 	client      *Client
@@ -57,6 +61,11 @@ func (di *DubboInvoker) Invoke(invocation protocol.Invocation) protocol.Result {
 	)
 
 	inv := invocation.(*invocation_impl.RPCInvocation)
+	for _, k := range attachmentKey {
+		if v := di.GetUrl().GetParam(k, ""); len(v) > 0 {
+			inv.SetAttachments(k, v)
+		}
+	}
 	url := di.GetUrl()
 	// async
 	async, err := strconv.ParseBool(inv.AttachmentsByKey(constant.ASYNC_KEY, "false"))