• 源码 grpc 认证 鸭子模型 函数返回值为接口 传输压缩 自定义令牌身份认证


    源码 grpc  认证 鸭子模型 

    Authentication | gRPC https://www.grpc.io/docs/guides/auth/#authenticate-with-google

    将谷歌的认证实现,改成定义的认证实现

    perRPC, _ := oauth.NewServiceAccountFromFile("service-account.json", scope)
    

     

    google.golang.org/grpc@v1.43.0/credentials/oauth/oauth.go:192

    // NewServiceAccountFromFile constructs the PerRPCCredentials using the JSON key file
    // of a Google Developers service account.
    func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.PerRPCCredentials, error) {
    jsonKey, err := ioutil.ReadFile(keyFile)
    if err != nil {
    return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err)
    }
    return NewServiceAccountFromKey(jsonKey, scope...)
    }

    关注返回值

    google.golang.org/grpc@v1.43.0/credentials/credentials.go:38

    // PerRPCCredentials defines the common interface for the credentials which need to
    // attach security information to every RPC (e.g., oauth2).
    type PerRPCCredentials interface {
    // GetRequestMetadata gets the current request metadata, refreshing
    // tokens if required. This should be called by the transport layer on
    // each request, and the data should be populated in headers or other
    // context. If a status code is returned, it will be used as the status
    // for the RPC. uri is the URI of the entry point for the request.
    // When supported by the underlying implementation, ctx can be used for
    // timeout and cancellation. Additionally, RequestInfo data will be
    // available via ctx to this call.
    // TODO(zhaoq): Define the set of the qualified keys instead of leaving
    // it as an arbitrary string.
    GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
    // RequireTransportSecurity indicates whether the credentials requires
    // transport security.
    RequireTransportSecurity() bool
    }

    其中原返回值为Google的逻辑

    // NewServiceAccountFromKey constructs the PerRPCCredentials using the JSON key slice
    // from a Google Developers service account.
    func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.PerRPCCredentials, error) {
    config, err := google.JWTConfigFromJSON(jsonKey, scope...)
    if err != nil {
    return nil, err
    }
    return &serviceAccount{config: config}, nil
    }

    实现方法


    type T struct {
    }

    func NewCustomerPerRPCCredentials() (PerRPCCredentials, error) {
    return &T{}, nil
    }
    func (t *T) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
    return nil, nil
    }

    func (t *T) RequireTransportSecurity() bool {
    return true
    }
    perRPC, err := NewCustomerPerRPCCredentials()

     鸭子能走路,能走路的就是鸭子。

     google.golang.org/grpc@v1.43.0/credentials/oauth/oauth.go:151


    // serviceAccount represents PerRPCCredentials via JWT signing key.
    type serviceAccount struct {
    mu sync.Mutex
    config *jwt.Config
    t *oauth2.Token
    }

    func (s *serviceAccount) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
    s.mu.Lock()
    defer s.mu.Unlock()
    if !s.t.Valid() {
    var err error
    s.t, err = s.config.TokenSource(ctx).Token()
    if err != nil {
    return nil, err
    }
    }
    ri, _ := credentials.RequestInfoFromContext(ctx)
    if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
    return nil, fmt.Errorf("unable to transfer serviceAccount PerRPCCredentials: %v", err)
    }
    return map[string]string{
    "authorization": s.t.Type() + " " + s.t.AccessToken,
    }, nil
    }

    func (s *serviceAccount) RequireTransportSecurity() bool {
    return true
    }
    google.golang.org/grpc v1.43.0
    google.golang.org/protobuf v1.27.1
    package grpc

    import (
    "context"
    "crypto/tls"
    "crypto/x509"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
    "google.golang.org/grpc/encoding/gzip"
    "io/ioutil"
    "time"
    )

    type T struct {
    AccessToken string
    }

    func NewCustomerPerRPCCredentials(AccessToken string) (credentials.PerRPCCredentials, error) {
    return &T{AccessToken: AccessToken}, nil
    }
    func (t *T) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
    m := map[string]string{}
    m["AccessToken"] = t.AccessToken
    return m, nil
    }

    func (t *T) RequireTransportSecurity() bool {
    return true
    }

    func NewConn() (conn *grpc.ClientConn) {
    certFile := "../cert/server1_cert.pem"
    //creds, err := credentials.NewClientTLSFromFile(certFile, "")
    b, err := ioutil.ReadFile(certFile)
    if err != nil {
    panic(err)
    }
    creds_cp := x509.NewCertPool()
    if !creds_cp.AppendCertsFromPEM(b) {
    panic("credentials: failed to append certificates")
    }
    creds, err := credentials.NewTLS(&tls.Config{ServerName: "", RootCAs: creds_cp, InsecureSkipVerify: true}), nil
    if err != nil {
    panic(err)
    }
    perRPC, err := NewCustomerPerRPCCredentials("Val-ak123")
    if err != nil {
    panic(err)
    }

    bytes := 1024 * 1024 * 4 * 4
    cp := grpc.ConnectParams{}
    cp.MinConnectTimeout = 16 * time.Second

    co := []grpc.CallOption{grpc.UseCompressor(gzip.Name)}

    opts := []grpc.DialOption{
    grpc.WithTransportCredentials(creds),
    grpc.WithBlock(),
    grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(bytes)),
    grpc.WithConnectParams(cp),
    grpc.WithDefaultCallOptions(co...),
    grpc.WithPerRPCCredentials(perRPC),
    }
    grpc.UseCompressor(gzip.Name)
    conn, err = grpc.Dial("1.24.14.14:12345", opts...)
    if err != nil {
    panic(err)
    }
    return conn
    }




    证书不被信任

    InsecureSkipVerify: true,         // test server certificate is not trusted.

    Go/src/crypto/tls/example_test.go:99

    client := &http.Client{
    Transport: &http.Transport{
    TLSClientConfig: &tls.Config{
    KeyLogWriter: w,

    Rand: zeroSource{}, // for reproducible output; don't do this.
    InsecureSkipVerify: true, // test server certificate is not trusted.
    },
    },
    }
    // InsecureSkipVerify controls whether a client verifies the server's
    // certificate chain and host name. If InsecureSkipVerify is true, crypto/tls
    // accepts any certificate presented by the server and any host name in that
    // certificate. In this mode, TLS is susceptible to machine-in-the-middle
    // attacks unless custom verification is used. This should be used only for
    // testing or in combination with VerifyConnection or VerifyPeerCertificate.
    InsecureSkipVerify bool

    Go/src/crypto/tls/common.go:646

    Go当中TLS/SSL 证书的实践 - 知乎 https://zhuanlan.zhihu.com/p/338688506

    github.com\robfig\cron\v3@v3.0.0\cron.go

    // Job is an interface for submitted cron jobs.
    type Job interface {
        Run()
    }
     
    // FuncJob is a wrapper that turns a func() into a cron.Job
    type FuncJob func()

    func (f FuncJob) Run() { f() }

    // AddFunc adds a func to the Cron to be run on the given schedule.
    // The spec is parsed using the time zone of this Cron instance as the default.
    // An opaque ID is returned that can be used to later remove it.
    func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error) {
        return c.AddJob(spec, FuncJob(cmd))
    }
     
     
    // FuncJob is a wrapper that turns a func() into a cron.Job
    type FuncJob func()

    func (f FuncJob) Run() { f() }

    // AddFunc adds a func to the Cron to be run on the given schedule.
    // The spec is parsed using the time zone of this Cron instance as the default.
    // An opaque ID is returned that can be used to later remove it.
    func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error) {
        return c.AddJob(spec, FuncJob(cmd))
    }

    // AddJob adds a Job to the Cron to be run on the given schedule.
    // The spec is parsed using the time zone of this Cron instance as the default.
    // An opaque ID is returned that can be used to later remove it.
    func (c *Cron) AddJob(spec string, cmd Job) (EntryID, error) {
        schedule, err := c.parser.Parse(spec)
        if err != nil {
            return 0, err
        }
        return c.Schedule(schedule, cmd), nil
    }
     
     
    type myJob struct {
        uri string
    }

    func (j myJob) Run() {
        openBrowser(j.uri)
    }
     
     
    函数类型 结构体类型 接口类型
     
     
    github.com\go-kratos\kratos\v2@v2.1.2\config\config.go
    package config
    
    import (
    	"context"
    	"errors"
    	"reflect"
    	"sync"
    	"time"
    
    	"github.com/go-kratos/kratos/v2/log"
    
    	// init encoding
    	_ "github.com/go-kratos/kratos/v2/encoding/json"
    	_ "github.com/go-kratos/kratos/v2/encoding/proto"
    	_ "github.com/go-kratos/kratos/v2/encoding/xml"
    	_ "github.com/go-kratos/kratos/v2/encoding/yaml"
    )
    
    var (
    	// ErrNotFound is key not found.
    	ErrNotFound = errors.New("key not found")
    	// ErrTypeAssert is type assert error.
    	ErrTypeAssert = errors.New("type assert error")
    
    	_ Config = (*config)(nil)
    )
    
    // Observer is config observer.
    type Observer func(string, Value)
    
    // Config is a config interface.
    type Config interface {
    	Load() error
    	Scan(v interface{}) error
    	Value(key string) Value
    	Watch(key string, o Observer) error
    	Close() error
    }
    
    type config struct {
    	opts      options
    	reader    Reader
    	cached    sync.Map
    	observers sync.Map
    	watchers  []Watcher
    	log       *log.Helper
    }
    
    // New new a config with options.
    func New(opts ...Option) Config {
    	o := options{
    		logger:   log.DefaultLogger,
    		decoder:  defaultDecoder,
    		resolver: defaultResolver,
    	}
    	for _, opt := range opts {
    		opt(&o)
    	}
    	return &config{
    		opts:   o,
    		reader: newReader(o),
    		log:    log.NewHelper(o.logger),
    	}
    }
    
    func (c *config) watch(w Watcher) {
    	for {
    		kvs, err := w.Next()
    		if errors.Is(err, context.Canceled) {
    			c.log.Infof("watcher's ctx cancel : %v", err)
    			return
    		}
    		if err != nil {
    			time.Sleep(time.Second)
    			c.log.Errorf("failed to watch next config: %v", err)
    			continue
    		}
    		if err := c.reader.Merge(kvs...); err != nil {
    			c.log.Errorf("failed to merge next config: %v", err)
    			continue
    		}
    		if err := c.reader.Resolve(); err != nil {
    			c.log.Errorf("failed to resolve next config: %v", err)
    			continue
    		}
    		c.cached.Range(func(key, value interface{}) bool {
    			k := key.(string)
    			v := value.(Value)
    			if n, ok := c.reader.Value(k); ok && !reflect.DeepEqual(n.Load(), v.Load()) {
    				v.Store(n.Load())
    				if o, ok := c.observers.Load(k); ok {
    					o.(Observer)(k, v)
    				}
    			}
    			return true
    		})
    	}
    }
    
    func (c *config) Load() error {
    	for _, src := range c.opts.sources {
    		kvs, err := src.Load()
    		if err != nil {
    			return err
    		}
    		for _, v := range kvs {
    			c.log.Infof("config loaded: %s format: %s", v.Key, v.Format)
    		}
    		if err = c.reader.Merge(kvs...); err != nil {
    			c.log.Errorf("failed to merge config source: %v", err)
    			return err
    		}
    		w, err := src.Watch()
    		if err != nil {
    			c.log.Errorf("failed to watch config source: %v", err)
    			return err
    		}
    		c.watchers = append(c.watchers, w)
    		go c.watch(w)
    	}
    	if err := c.reader.Resolve(); err != nil {
    		c.log.Errorf("failed to resolve config source: %v", err)
    		return err
    	}
    	return nil
    }
    
    func (c *config) Value(key string) Value {
    	if v, ok := c.cached.Load(key); ok {
    		return v.(Value)
    	}
    	if v, ok := c.reader.Value(key); ok {
    		c.cached.Store(key, v)
    		return v
    	}
    	return &errValue{err: ErrNotFound}
    }
    
    func (c *config) Scan(v interface{}) error {
    	data, err := c.reader.Source()
    	if err != nil {
    		return err
    	}
    	return unmarshalJSON(data, v)
    }
    
    func (c *config) Watch(key string, o Observer) error {
    	if v := c.Value(key); v.Load() == nil {
    		return ErrNotFound
    	}
    	c.observers.Store(key, o)
    	return nil
    }
    
    func (c *config) Close() error {
    	for _, w := range c.watchers {
    		if err := w.Stop(); err != nil {
    			return err
    		}
    	}
    	return nil
    }
    

      

     
     
     
     
     
     
     
  • 相关阅读:
    poj 3264 Balanced Lineup
    poj 2762 Going from u to v or from v to u?
    hdu 3671 Boonie and Clyde
    zoj 3195 Design the city
    poj 1523 SPF
    Codeforces Polo the Penguin and Matrix
    MVC原理的简述(转)
    C#访问权限修饰符
    XML Schema介绍
    Sql批量删除/插入
  • 原文地址:https://www.cnblogs.com/rsapaper/p/15716337.html
Copyright © 2020-2023  润新知