GRPC CAPTCHA验证中间件是一个GO模块,它提供了可重复使用的中间件组件,用于验证GRPC服务器上的验证码挑战。中间件拦截传入请求,使用可配置的提供商验证请求的验证码挑战,并在挑战无效时拒绝请求。
该模块设计为可配置,并具有指定验证码提供商,挑战验证端点的选项以及验证请求的自定义标头。它使用Google Protobuf库来解析GRPC方法描述符,并提取使用Protobuf扩展定义的自定义选项。
特征
- 支持Google,Cloudflare,HCAPTCHA提供商验证挑战
- 支持Unary和流服务器中间件
- 特定RPC方法的CAPTCHA验证
安装(GO> = 1.18)
$ go get -u github.com/GoFarsi/grpc-captcha-validation
文档:https://pkg.go.dev/github.com/GoFarsi/grpc-captcha-validation
例子
GRPC服务器的示例CAPTCHA:
syntax = "proto3";
package example;
option go_package = "github.com/GoFarsi/grpc-captcha-validation/_example/proto";
import "captcha.proto";
service GreetingService {
rpc Greeting(GreetingRequest) returns(GreetingResponse) {
option(captcha.captcha) = {
check_challenge: true,
provider: GOOGLE,
};
}
rpc GreetingStream(stream GreetingRequest) returns(stream GreetingResponse) {
option(captcha.captcha) = {
check_challenge: true,
provider: GOOGLE,
};
}
}
message GreetingRequest {
string name = 1;
}
message GreetingResponse {
string message = 1;
}
package main
import (
"context"
"fmt"
gcv "github.com/GoFarsi/grpc-captcha-validation"
"github.com/GoFarsi/grpc-captcha-validation/_example/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"io"
"log"
"net"
)
type GreetingService struct {
proto.UnimplementedGreetingServiceServer
}
func (g *GreetingService) Greeting(ctx context.Context, in *proto.GreetingRequest) (*proto.GreetingResponse, error) {
return &proto.GreetingResponse{
Message: fmt.Sprintf("greeting %s", in.Name),
}, nil
}
func (g *GreetingService) GreetingStream(srv proto.GreetingService_GreetingStreamServer) error {
ctx := srv.Context()
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
req, err := srv.Recv()
if err == io.EOF {
log.Println("exit")
return nil
}
if err != nil {
log.Printf("receive error %v", err)
continue
}
resp := proto.GreetingResponse{Message: fmt.Sprintf("Greeting %s", req.Name)}
if err := srv.Send(&resp); err != nil {
log.Printf("send error %v", err)
}
}
}
func main() {
listener, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalln(err)
}
c := gcv.NewCaptcha("foo", "", "", "")
srv := grpc.NewServer(
grpc.ChainUnaryInterceptor(c.UnaryServerInterceptor()),
grpc.ChainStreamInterceptor(c.StreamServerInterceptor()),
)
reflection.Register(srv)
proto.RegisterGreetingServiceServer(srv, &GreetingService{})
log.Fatalln(srv.Serve(listener))
}