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()), // 添加认证插件
	)

若账号密码错误返回:

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

相关推荐
高频因子挖掘机34 分钟前
同一交易日出现重复 K 线:去重前先确认时间、来源和粒度
后端·github·api
feely02081 小时前
《我写了 31 个静态扫描插件,踩了 7 个「假绿」》
后端
橙子家2 小时前
参数校验类异常(Argument Exception)【C# Exception 详解系列一】
后端
掘金挖土2 小时前
前端手摸手跑路之 AI 应用开发(九)
前端·后端
全栈弄潮儿3 小时前
Python实战第8期:函数
后端·python·编程语言
码事漫谈3 小时前
你让 AI “尽力做”,它反而可能做不好
后端
孟健4 小时前
LLM API 安全防线:从 OpenCode 盗刷事件到 LiteLLM 多模型容灾实操
人工智能·后端·架构
程序员cxuan4 小时前
我用 WorkBuddy + ima 把公众号文章做成了知识库。
人工智能·后端·程序员
程序员cxuan5 小时前
玩了一天 REA,我号快没了
人工智能·后端·程序员