补充grpc认证
This commit is contained in:
parent
afa7743e82
commit
4a0ed93617
56
skills/rpc/protobuf/hello_service/client_auther.go
Normal file
56
skills/rpc/protobuf/hello_service/client_auther.go
Normal file
@ -0,0 +1,56 @@
|
||||
package hello_service
|
||||
|
||||
import context "context"
|
||||
|
||||
// PerRPCCredentials defines the common interface for the credentials which need to
|
||||
// attach security information to every RPC (e.g., oauth2).
|
||||
// type PerRPCCredentials interface {
|
||||
// // GetRequestMetadata gets the current request metadata, refreshing tokens
|
||||
// // if required. This should be called by the transport layer on each
|
||||
// // request, and the data should be populated in headers or other
|
||||
// // context. If a status code is returned, it will be used as the status for
|
||||
// // the RPC (restricted to an allowable set of codes as defined by gRFC
|
||||
// // A54). uri is the URI of the entry point for the request. When supported
|
||||
// // by the underlying implementation, ctx can be used for timeout and
|
||||
// // cancellation. Additionally, RequestInfo data will be available via ctx
|
||||
// // to this call. TODO(zhaoq): Define the set of the qualified keys instead
|
||||
// // of leaving it as an arbitrary string.
|
||||
// GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
|
||||
// // RequireTransportSecurity indicates whether the credentials requires
|
||||
// // transport security.
|
||||
// RequireTransportSecurity() bool
|
||||
// }
|
||||
|
||||
func NewClientAuthentication(clientId, clientSecret string) *Authentication {
|
||||
return &Authentication{
|
||||
clientID: clientId,
|
||||
clientSecret: clientSecret,
|
||||
}
|
||||
}
|
||||
|
||||
// Authentication todo
|
||||
type Authentication struct {
|
||||
clientID string
|
||||
clientSecret string
|
||||
}
|
||||
|
||||
// WithClientCredentials todo
|
||||
func (a *Authentication) WithClientCredentials(clientID, clientSecret string) {
|
||||
a.clientID = clientID
|
||||
a.clientSecret = clientSecret
|
||||
}
|
||||
|
||||
// GetRequestMetadata todo
|
||||
func (a *Authentication) GetRequestMetadata(context.Context, ...string) (
|
||||
map[string]string, error,
|
||||
) {
|
||||
return map[string]string{
|
||||
ClientHeaderKey: a.clientID,
|
||||
ClientSecretKey: a.clientSecret,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RequireTransportSecurity todo
|
||||
func (a *Authentication) RequireTransportSecurity() bool {
|
||||
return false
|
||||
}
|
90
skills/rpc/protobuf/hello_service/middleware.go
Normal file
90
skills/rpc/protobuf/hello_service/middleware.go
Normal file
@ -0,0 +1,90 @@
|
||||
package hello_service
|
||||
|
||||
import (
|
||||
context "context"
|
||||
"fmt"
|
||||
|
||||
"github.com/infraboard/mcube/v2/ioc/config/log"
|
||||
"github.com/rs/zerolog"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
ClientHeaderKey = "client-id"
|
||||
ClientSecretKey = "client-secret"
|
||||
)
|
||||
|
||||
// GrpcAuthUnaryServerInterceptor returns a new unary server interceptor for auth.
|
||||
func GrpcAuthUnaryServerInterceptor() grpc.UnaryServerInterceptor {
|
||||
return newGrpcAuther().Auth
|
||||
}
|
||||
|
||||
func newGrpcAuther() *grpcAuther {
|
||||
return &grpcAuther{
|
||||
log: log.Sub("Grpc Auther"),
|
||||
}
|
||||
}
|
||||
|
||||
// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
|
||||
// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
|
||||
// of the service method implementation. It is the responsibility of the interceptor to invoke handler
|
||||
// to complete the RPC.
|
||||
// type UnaryServerInterceptor func(ctx context.Context, req any, info *UnaryServerInfo, handler UnaryHandler) (resp any, err error)
|
||||
// internal todo
|
||||
type grpcAuther struct {
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
func (a *grpcAuther) Auth(
|
||||
ctx context.Context, req any,
|
||||
info *grpc.UnaryServerInfo,
|
||||
handler grpc.UnaryHandler,
|
||||
) (resp any, err error) {
|
||||
// http2 header -> metadata
|
||||
// 重上下文中获取认证信息
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("ctx is not an grpc incoming context")
|
||||
}
|
||||
|
||||
fmt.Println("gprc header info: ", md)
|
||||
|
||||
clientId, clientSecret := a.GetClientCredentialsFromMeta(md)
|
||||
|
||||
// 校验调用的客户端凭证是否有效
|
||||
if err := a.validateServiceCredential(clientId, clientSecret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 把请求交给后续的Handler处理
|
||||
resp, err = handler(ctx, req)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (a *grpcAuther) 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 *grpcAuther) 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
|
||||
}
|
@ -12,7 +12,8 @@ import (
|
||||
|
||||
func main() {
|
||||
// 首先是通过grpc.NewServer()构造一个gRPC服务对象
|
||||
grpcServer := grpc.NewServer()
|
||||
// 补充了全局的认证中间件
|
||||
grpcServer := grpc.NewServer(grpc.ChainUnaryInterceptor(hello_service.GrpcAuthUnaryServerInterceptor()))
|
||||
|
||||
// SDK 提供 服务实现对象的注册
|
||||
hello_service.RegisterHelloServiceServer(grpcServer, &HelloService{})
|
||||
|
@ -14,7 +14,12 @@ import (
|
||||
|
||||
func main() {
|
||||
// grpc.Dial负责和gRPC服务建立链接
|
||||
conn, err := grpc.NewClient("localhost:1234", grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
conn, err := grpc.NewClient("localhost:1234",
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithPerRPCCredentials(hello_service.NewClientAuthentication(
|
||||
"admin",
|
||||
"123456",
|
||||
)))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user