在 gRPC 中,可以使用 TLS/SSL 或 Token 认证来进行身份验证。以下是如何实现这两种认证方式的示例:

  1. TLS/SSL 认证:

使用 TLS/SSL 认证时,客户端和服务器都需要使用 SSL 证书进行身份验证和加密通信。

服务器端:

package main

import (
    "crypto/tls"
    "log"
    "net"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
    "your_package/your_proto"
)

func main() {
    // Load server certificate and key
    creds, err := credentials.NewServerTLSFromFile("server.crt", "server.key")
    if err != nil {
        log.Fatalf("Failed to load server credentials: %v", err)
    }

    // Create a gRPC server with TLS credentials
    server := grpc.NewServer(grpc.Creds(creds))
    your_proto.RegisterYourServiceServer(server, &YourService{})

    // Start listening on a port
    listener, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("Failed to listen: %v", err)
    }
    if err := server.Serve(listener); err != nil {
        log.Fatalf("Failed to serve: %v", err)
    }
}

客户端:

package main

import (
    "log"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
    "your_package/your_proto"
)

func main() {
    // Load client certificate and key
    creds, err := credentials.NewClientTLSFromFile("server.crt", "")
    if err != nil {
        log.Fatalf("Failed to load client credentials: %v", err)
    }

    // Dial the gRPC server with TLS credentials
    conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds))
    if err != nil {
        log.Fatalf("Failed to dial: %v", err)
    }
    defer conn.Close()

    // Use the conn to create a client and make RPC calls
    client := your_proto.NewYourServiceClient(conn)
    // ...
}
  1. Token 认证:

在 gRPC 中,WithPerRPCCredentials 接口用于为每个 RPC 调用设置自定义的认证凭据。这使得在每个单独的 RPC 调用中都可以使用不同的认证信息。这种方法适用于需要每个 RPC 调用使用不同凭据的情况,比如使用短期令牌或动态生成的凭据。

WithPerRPCCredentials 的签名如下:

func WithPerRPCCredentials(creds PerRPCCredentials) DialOption

这里的 PerRPCCredentials 是一个接口,你需要实现这个接口来定义你自己的认证逻辑。接口定义如下:

type PerRPCCredentials interface {
    GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
    RequireTransportSecurity() bool
}
  • GetRequestMetadata 方法用于返回用于当前 RPC 调用的认证元数据,通常是一个键值对的映射。这些元数据将被添加到 gRPC 请求的标头中,用于认证。你可以在这里添加自己的认证信息。
  • RequireTransportSecurity 方法指示是否需要传输层安全,通常返回 true

以下是一个简单的示例,展示如何使用 WithPerRPCCredentials 接口为每个 RPC 调用设置自定义的 Token 认证凭据:

package main

import (
	"context"
	"log"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

type TokenCredential struct {
	Token string
}

func (t TokenCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	return map[string]string{
		"authorization": "Bearer " + t.Token,
	}, nil
}

func (t TokenCredential) RequireTransportSecurity() bool {
	return true
}

func main() {
	creds := TokenCredential{
		Token: "your_access_token",
	}

	opts := []grpc.DialOption{
		grpc.WithTransportCredentials(credentials.NewTLS(nil)),
		grpc.WithPerRPCCredentials(creds),
	}

	conn, err := grpc.Dial("localhost:50051", opts...)
	if err != nil {
		log.Fatalf("Failed to dial: %v", err)
	}
	defer conn.Close()

	// Use the connection for RPC calls
	// ...
}

在上面的示例中,TokenCredential 结构实现了 PerRPCCredentials 接口,用于设置每个 RPC 调用的认证元数据。通过使用 WithPerRPCCredentials 接口,我们将自定义的 Token 认证凭据应用于 gRPC 连接,并为每个 RPC 调用添加了认证标头。

以上示例演示了如何在 gRPC 中实现 TLS/SSL 和 Token 认证。选择适合你项目需求的认证方式,并根据实际情况进行配置。


孟斯特

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意