Golang Grpc接口调用实现账号密码认证

GRPC实现案例

1.客户端认证凭证实现
Go 复制代码
package auth

import "context"

type Authentication struct {
	clientId     string
	clientSecret string
}

// 构造凭证
func NewClientAuthentication(clientId, clientSecret string) *Authentication {
	return &Authentication{
		clientId:     clientId,
		clientSecret: clientSecret,
	}
}

// 初始化凭证
func (a *Authentication) InitClientCredentials(clientId, clientSecret string) {
	a.clientId = clientId
	a.clientSecret = clientSecret
}

// 获取凭证
func (a *Authentication) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
	return map[string]string{
		"clientId":     a.clientId,
		"clientSecret": a.clientSecret,
	}, nil
}

// 凭证是否需要安全传输
func (a *Authentication) RequireTransportSecurity() bool {
	return false
}

客户端连接设置

Go 复制代码
conn, err := grpc.NewClient(addr,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithPerRPCCredentials(auth.NewClientAuthentication("admin", "123456")))
2.服务端认证实现
Go 复制代码
package auth

import (
	"context"
	"fmt"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

const (
	ClientHeaderKey = "clientId"
	ClientSecretKey = "clientSecret"
)

type GrpcAuthor struct {

}

// 构造并初始化
func NewGrpcAuthor() *GrpcAuthor {
	return &GrpcAuthor{}
}

// 从客户端发来的请求中获取凭证信息
func (a *GrpcAuthor) GetClientCredentialsFromMeta(md metadata.MD) (
	clientId, clientSecret string) {
	cids := md.Get(ClientHeaderKey)
	sids := md.Get(ClientSecretKey)
	if len(cids) > 0 {
		clientId = cids[0]
	}
	if len(sids) > 0 {
		clientSecret = sids[0]
	}
	return
}

// 验证凭证信息
func (a *GrpcAuthor) validateServiceCredential(clientId, clientSecret string) error {
	if clientId == "" && clientSecret == "" {
		return status.Errorf(codes.Unauthenticated, "client_id or client_secret is \"\"")
	}
	if !(clientId == "admin" && clientSecret == "123456") {
		return status.Errorf(codes.Unauthenticated, "client_id or client_secret invalidate")
	}
	return nil
}

// 拦截器
func (a *GrpcAuthor) Auth(
	ctx context.Context,
	req interface{},
	info *grpc.UnaryServerInfo,
	handler grpc.UnaryHandler,
) (resp interface{}, err error) {
	// 从上下文中获取认证信息
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, fmt.Errorf("ctx is not an grpc incoming context!")
	}

	fmt.Println("grpc header info :", md)

	// 获取客户端凭证信息
	clientId, clientSecret := a.GetClientCredentialsFromMeta(md)

	// 校验调用的客户端携带的凭证是否有效
	if err := a.validateServiceCredential(clientId, clientSecret); err != nil {
		return nil, err
	}

	resp, err = handler(ctx, req)
	return resp, err
}

func GrpcAuthUnaryServerInterceptor() grpc.UnaryServerInterceptor {
	return NewGrpcAuthor().Auth
}

服务端提供设置

Go 复制代码
s := grpc.NewServer(
		grpc.UnaryInterceptor(auth.GrpcAuthUnaryServerInterceptor()), // 添加认证插件
	)

若账号密码错误返回:

具体的案例实现,修改其中部分即可验证。

相关推荐
J_liaty2 小时前
SpringBoot整合Canal实现数据库实时同步
数据库·spring boot·后端·canal
EQ-雪梨蛋花汤2 小时前
【问题反馈】JNI 开发:为什么 C++ 在 Debug 正常,Release 却返回 NaN?
开发语言·c++
naruto_lnq2 小时前
高性能消息队列实现
开发语言·c++·算法
charlie1145141912 小时前
malloc 在多线程下为什么慢?——从原理到实测
开发语言·c++·笔记·学习·工程实践
JaguarJack2 小时前
Laravel AI SDK 在 Laracon India 2026 首次亮相
后端·php·laravel
kyrie学java2 小时前
SpringWeb
java·开发语言
写代码的【黑咖啡】2 小时前
Python 中的 Gensim 库详解
开发语言·python
小二·2 小时前
Go 语言系统编程与云原生开发实战(第6篇)云原生部署实战:Docker 镜像瘦身 × K8s 部署 × Helm 一键发布
docker·云原生·golang
bjxiaxueliang4 小时前
一文掌握SpringBoot:HTTP服务开发从入门到部署
spring boot·后端·http