本文主要研究一下rocketmq-client-go的ACLInterceptorapp
rocketmq-client-go-v2.0.0/internal/remote/interceptor.gothis
func ACLInterceptor(credentials primitive.Credentials) primitive.Interceptor { return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error { cmd := req.(*RemotingCommand) m := make(map[string]string) order := make([]string, 1) m[accessKey] = credentials.AccessKey order[0] = accessKey if credentials.SecurityToken != "" { m[securityToken] = credentials.SecurityToken } for k, v := range cmd.ExtFields { m[k] = v order = append(order, k) } sort.Slice(order, func(i, j int) bool { return strings.Compare(order[i], order[j]) < 0 }) content := "" for idx := range order { content += m[order[idx]] } buf := make([]byte, len(content)+len(cmd.Body)) copy(buf, []byte(content)) copy(buf[len(content):], cmd.Body) cmd.ExtFields[signature] = calculateSignature(buf, []byte(credentials.SecretKey)) cmd.ExtFields[accessKey] = credentials.AccessKey // The SecurityToken value is unnecessary, user can choose this one. if credentials.SecurityToken != "" { cmd.ExtFields[securityToken] = credentials.SecurityToken } err := next(ctx, req, reply) return err } }
rocketmq-client-go-v2.0.0/internal/remote/interceptor.go編碼
func calculateSignature(data, sk []byte) string { mac := hmac.New(func() hash.Hash { return sha1.New() }, sk) mac.Write(data) return base64.StdEncoding.EncodeToString(mac.Sum(nil)) }
rocketmq-client-go-v2.0.0/internal/namesrv.gocode
func (s *namesrvs) SetCredentials(credentials primitive.Credentials) { s.nameSrvClient.RegisterInterceptor(remote.ACLInterceptor(credentials)) }
rocketmq-client-go-v2.0.0/internal/remote/remote_client.go遞歸
func (c *remotingClient) RegisterInterceptor(interceptors ...primitive.Interceptor) { c.interceptor = primitive.ChainInterceptors(interceptors...) }
rocketmq-client-go-v2.0.0/primitive/interceptor.gorem
func ChainInterceptors(interceptors ...Interceptor) Interceptor { if len(interceptors) == 0 { return nil } if len(interceptors) == 1 { return interceptors[0] } return func(ctx context.Context, req, reply interface{}, invoker Invoker) error { return interceptors[0](ctx, req, reply, getChainedInterceptor(interceptors, 0, invoker)) } }
rocketmq-client-go-v2.0.0/primitive/interceptor.goget
func getChainedInterceptor(interceptors []Interceptor, cur int, finalInvoker Invoker) Invoker { if cur == len(interceptors)-1 { return finalInvoker } return func(ctx context.Context, req, reply interface{}) error { return interceptors[cur+1](ctx, req, reply, getChainedInterceptor(interceptors, cur+1, finalInvoker)) } }
cur == len(interceptors)-1
ACLInterceptor方法會調用calculateSignature計算簽名,而後執行next;calculateSignature方法經過base64來將mac.Sum的結果編碼爲stringcmd