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

若账号密码错误返回:

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

相关推荐
m0_7166670720 小时前
C++中的访问者模式高级应用
开发语言·c++·算法
小江的记录本20 小时前
【会话:Cookie与Session】Cookie与Session的区别(附对比表)
java·数据库·后端·sql·http·https·安全架构
大鹏说大话20 小时前
构建高并发缓存系统:架构设计、Redis策略与灾难防御
开发语言
Oueii20 小时前
C++中的访问者模式变体
开发语言·c++·算法
2401_8386833720 小时前
单元测试在C++项目中的实践
开发语言·c++·算法
凤山老林20 小时前
Tomcat 高高在上?0-1 实现一个简单的 WEB 容器
java·后端·tomcat·web容器
guygg8820 小时前
基于Kaimal谱的风速时间序列生成MATLAB程序
开发语言·matlab
执行部之龙20 小时前
js手写——防抖
开发语言·前端·javascript
DEMO派20 小时前
JavaScript数据存储三剑客:Object、Map与WeakMap完全指南
开发语言·前端·javascript
窝子面20 小时前
一、用户系统
后端