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

若账号密码错误返回:

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

相关推荐
阿狗童鞋几秒前
SpringBoot微服务实战指南
spring boot·后端·微服务
FfHUCisI2 分钟前
sync.Once 与 sync.Cond 源码与并发控制陷阱
服务器·开发语言·后端·golang
阿钱真强道7 分钟前
21 嵌入式操作系统 | JSON 与 json-c:生成与解析
c语言·开发语言·json·json-c
j7~8 分钟前
【Python】(篇六)《基础语法(函数、列表和元组、字典、文件)》---详解
开发语言·python·文件·函数·字典·编程学习·元组与列表
montEvergreen8 分钟前
位运算不是魔法——AV1 配置解析实战
后端
重生之小比特20 分钟前
【C++进阶】红黑树的实现
java·开发语言·c++
纪念 22921 分钟前
C++算法(一)
开发语言·c++·算法
程序猿乐锅25 分钟前
【黑马点评 | 第九篇】秒杀优化-异步实现
java·spring boot·redis·后端·spring·中间件·mybatis
Wx-bishekaifayuan34 分钟前
springboot户外登山社交小程序19787-计算机课程设计、毕业设计
spring boot·后端·python·spring·elasticsearch·django·课程设计
+VX:Fegn089538 分钟前
计算机毕业设计|基于springboot + vue外卖点餐系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计