dubbo.apache.org/dubbo-go/v3@v3.1.1/filter/token/filter.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 // Package token provides token filter. 19 package token 20 21 import ( 22 "context" 23 "strings" 24 "sync" 25 ) 26 27 import ( 28 perrors "github.com/pkg/errors" 29 ) 30 31 import ( 32 "dubbo.apache.org/dubbo-go/v3/common/constant" 33 "dubbo.apache.org/dubbo-go/v3/common/extension" 34 "dubbo.apache.org/dubbo-go/v3/filter" 35 "dubbo.apache.org/dubbo-go/v3/protocol" 36 ) 37 38 var ( 39 once sync.Once 40 token *tokenFilter 41 ) 42 43 func init() { 44 extension.SetFilter(constant.TokenFilterKey, newTokenFilter) 45 } 46 47 const ( 48 InValidTokenFormat = "[Token Filter]Invalid token! Forbid invoke remote service %v with method %s" 49 ) 50 51 // tokenFilter will verify if the token is valid 52 type tokenFilter struct{} 53 54 func newTokenFilter() filter.Filter { 55 if token == nil { 56 once.Do(func() { 57 token = &tokenFilter{} 58 }) 59 } 60 return token 61 } 62 63 // Invoke verifies the incoming token with the service configured token 64 func (f *tokenFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { 65 invokerTkn := invoker.GetURL().GetParam(constant.TokenKey, "") 66 if len(invokerTkn) > 0 { 67 attas := invocation.Attachments() 68 var remoteTkn string 69 remoteTknIface, exist := attas[constant.TokenKey] 70 if !exist || remoteTknIface == nil { 71 return &protocol.RPCResult{Err: perrors.Errorf(InValidTokenFormat, invoker, invocation.MethodName())} 72 } 73 switch remoteTknIface.(type) { 74 case string: 75 // deal with dubbo protocol 76 remoteTkn = remoteTknIface.(string) 77 case []string: 78 // deal with triple protocol 79 remoteTkns := remoteTknIface.([]string) 80 if len(remoteTkns) != 1 { 81 return &protocol.RPCResult{Err: perrors.Errorf(InValidTokenFormat, invoker, invocation.MethodName())} 82 } 83 remoteTkn = remoteTkns[0] 84 default: 85 return &protocol.RPCResult{Err: perrors.Errorf(InValidTokenFormat, invoker, invocation.MethodName())} 86 } 87 88 if strings.EqualFold(invokerTkn, remoteTkn) { 89 return invoker.Invoke(ctx, invocation) 90 } 91 return &protocol.RPCResult{Err: perrors.Errorf(InValidTokenFormat, invoker, invocation.MethodName())} 92 } 93 94 return invoker.Invoke(ctx, invocation) 95 } 96 97 // OnResponse dummy process, returns the result directly 98 func (f *tokenFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { 99 return result 100 }