美文网首页
gRPC授权访问CA(Certificate Authority

gRPC授权访问CA(Certificate Authority

作者: 渣渣曦 | 来源:发表于2019-06-20 19:28 被阅读0次

    下载代码:
    https://golang.org/src/crypto/tls/generate_cert.go
    生成公钥及私钥:

    go run generate_cert.go --host server.io
    

    服务端代码server.go:

    package main
    
    import (
        "context"
        "crypto/tls"
        "flag"
        "fmt"
        "log"
        "net"
        "strings"
    
        "google.golang.org/grpc"
        "google.golang.org/grpc/codes"
        "google.golang.org/grpc/credentials"
        ecpb "google.golang.org/grpc/examples/features/proto/echo"
        "google.golang.org/grpc/metadata"
        "google.golang.org/grpc/status"
    )
    
    var (
        errMissingMetadata = status.Errorf(codes.InvalidArgument, "missing metadata")
        errInvalidToken    = status.Errorf(codes.Unauthenticated, "invalid token")
    )
    
    var port = flag.Int("port", 50051, "the port to serve on")
    
    func main() {
        flag.Parse()
        fmt.Printf("server starting on port %d...\n", *port)
    
        cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
        if err != nil {
            log.Fatalf("failed to load key pair: %s", err)
        }
        opts := []grpc.ServerOption{
            // token拦截器
            grpc.UnaryInterceptor(ensureValidToken),
            // Enable TLS for all incoming connections.
            grpc.Creds(credentials.NewServerTLSFromCert(&cert)),
        }
        s := grpc.NewServer(opts...)
        ecpb.RegisterEchoServer(s, &ecServer{})
        lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
        if err != nil {
            log.Fatalf("failed to listen: %v", err)
        }
        if err := s.Serve(lis); err != nil {
            log.Fatalf("failed to serve: %v", err)
        }
    }
    
    type ecServer struct{}
    
    func (s *ecServer) UnaryEcho(ctx context.Context, req *ecpb.EchoRequest) (*ecpb.EchoResponse, error) {
        return &ecpb.EchoResponse{Message: req.Message}, nil
    }
    func (s *ecServer) ServerStreamingEcho(*ecpb.EchoRequest, ecpb.Echo_ServerStreamingEchoServer) error {
        return status.Errorf(codes.Unimplemented, "not implemented")
    }
    func (s *ecServer) ClientStreamingEcho(ecpb.Echo_ClientStreamingEchoServer) error {
        return status.Errorf(codes.Unimplemented, "not implemented")
    }
    func (s *ecServer) BidirectionalStreamingEcho(ecpb.Echo_BidirectionalStreamingEchoServer) error {
        return status.Errorf(codes.Unimplemented, "not implemented")
    }
    
    // valid validates the authorization.
    func valid(authorization []string) bool {
        if len(authorization) < 1 {
            return false
        }
        token := strings.TrimPrefix(authorization[0], "Bearer ")
        // Token验证代码.
        return token == "some-secret-token"
    }
    
    // 验证Token
    func ensureValidToken(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
        md, ok := metadata.FromIncomingContext(ctx)
        if !ok {
            return nil, errMissingMetadata
        }
        // The keys within metadata.MD are normalized to lowercase.
        // See: https://godoc.org/google.golang.org/grpc/metadata#New
        if !valid(md["authorization"]) {
            return nil, errInvalidToken
        }
        // Continue execution of handler after ensuring a valid token.
        return handler(ctx, req)
    }
    

    客户端代码client.go

    package main
    
    import (
        "context"
        "flag"
        "fmt"
        "log"
        "time"
    
        "golang.org/x/oauth2"
        "google.golang.org/grpc"
        "google.golang.org/grpc/credentials"
        "google.golang.org/grpc/credentials/oauth"
        ecpb "google.golang.org/grpc/examples/features/proto/echo"
    )
    
    var addr = flag.String("addr", "localhost:50051", "the address to connect to")
    
    func callUnaryEcho(client ecpb.EchoClient, message string) {
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        resp, err := client.UnaryEcho(ctx, &ecpb.EchoRequest{Message: message})
        if err != nil {
            log.Fatalf("client.UnaryEcho(_) = _, %v: ", err)
        }
        fmt.Println("UnaryEcho: ", resp.Message)
    }
    
    func main() {
        flag.Parse()
    
        // Set up the credentials for the connection.
        perRPC := oauth.NewOauthAccess(fetchToken())
        creds, err := credentials.NewClientTLSFromFile("cert.pem", "server.io")
        if err != nil {
            log.Fatalf("failed to load credentials: %v", err)
        }
        opts := []grpc.DialOption{
            // In addition to the following grpc.DialOption, callers may also use
            // the grpc.CallOption grpc.PerRPCCredentials with the RPC invocation
            // itself.
            // See: https://godoc.org/google.golang.org/grpc#PerRPCCredentials
            grpc.WithPerRPCCredentials(perRPC),
            // oauth.NewOauthAccess requires the configuration of transport
            // credentials.
            grpc.WithTransportCredentials(creds),
        }
    
        conn, err := grpc.Dial(*addr, opts...)
        if err != nil {
            log.Fatalf("did not connect: %v", err)
        }
        defer conn.Close()
        rgc := ecpb.NewEchoClient(conn)
    
        callUnaryEcho(rgc, "hello world")
    }
    
    // fetchToken simulates a token lookup and omits the details of proper token
    // acquisition. For examples of how to acquire an OAuth2 token, see:
    // https://godoc.org/golang.org/x/oauth2
    func fetchToken() *oauth2.Token {
        return &oauth2.Token{
            AccessToken: "some-secret-token",
        }
    }
    

    相关文章

      网友评论

          本文标题:gRPC授权访问CA(Certificate Authority

          本文链接:https://www.haomeiwen.com/subject/eitsqctx.html