hello.proto
syntax = "proto3";
option go_package ="./;proto";
service Server {
rpc SayHello(HelloReq) returns (HelloRes);
}
message HelloReq{
string name = 1;
}
message HelloRes{
string msg = 1;
}
proto生成go文件命令
protoc --go_out=. --go-grpc_out=. hello.proto
client.go
方法一:自定义拦截器,实现统一参数校验
package main
import (
"Go_Bible/grpc_token_auth_test/proto"
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
func main() {
authInterceptor := func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
md := metadata.New(map[string]string{
"appid": "10010",
"access_key": "1234",
})
ctx = metadata.NewOutgoingContext(ctx, md)
err := invoker(ctx, method, req, reply, cc, opts...)
if err != nil {
fmt.Println("客户端接口调用错误-->" + err.Error())
}
return err
}
opt := grpc.WithUnaryInterceptor(authInterceptor)
var opts []grpc.DialOption
opts = append(opts, opt)
opts = append(opts, grpc.WithInsecure())
conn, err := grpc.Dial("localhost:15001", opts...)
if err != nil {
panic("客户端拨号失败-->" + err.Error())
}
client := proto.NewServerClient(conn)
res, err := client.SayHello(context.Background(), &proto.HelloReq{
Name: "kevin",
})
if err != nil {
panic("客户端调用SayHello接口失败-->" + err.Error() + "\n")
}
fmt.Println("客户端调用接口成功:" + res.Msg)
}
方法二:使用grpc内置拦截器,需要自定义结构体,实现credentials.PerRPCCredentials接口中的方法
package main
import (
"Go_Bible/grpc_token_auth_test/proto"
"context"
"fmt"
"google.golang.org/grpc"
)
type customCredential struct{}
func (c customCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error){
return map[string]string{
"appid" : "10010",
"access_key" : "1234",
}, nil
}
func (c customCredential) RequireTransportSecurity() bool{
return false
}
func main() {
opt := grpc.WithPerRPCCredentials(customCredential{})
var opts []grpc.DialOption
opts = append(opts, opt)
opts = append(opts, grpc.WithInsecure())
conn, err := grpc.Dial("localhost:15001", opts...)
if err != nil {
panic("客户端拨号失败-->" + err.Error())
}
client := proto.NewServerClient(conn)
res, err := client.SayHello(context.Background(), &proto.HelloReq{
Name: "kevin",
})
if err != nil {
panic("客户端调用SayHello接口失败-->" + err.Error() + "\n")
}
fmt.Println("客户端调用接口成功:" + res.Msg)
}
server.go
package main
import (
"Go_Bible/grpc_token_auth_test/proto"
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"net"
)
type Server struct {
proto.UnimplementedServerServer
}
func (s *Server) SayHello(ctx context.Context, req *proto.HelloReq) (*proto.HelloRes, error) {
return &proto.HelloRes{
Msg: "Hello : " + req.Name,
}, nil
}
func main() {
interceptor := func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
fmt.Println("服务端开始对接口拦截")
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
fmt.Println("服务端获取元数据失败")
return resp, status.Error(codes.Unauthenticated, "服务端获取metadata失败")
}
var (
appid string
access_key string
)
if val, ok := md["appid"]; ok {
appid = val[0]
}
if val, ok := md["access_key"]; ok {
access_key = val[0]
}
if appid != "10010" || access_key != "1234" {
return resp, status.Error(codes.Unauthenticated, "服务端接口校验失败")
}
fmt.Println("服务端接口统一校验通过")
resp, err = handler(ctx, req)
fmt.Println("服务端接口拦截结束")
return resp, err
}
opt := grpc.UnaryInterceptor(interceptor)
var opts []grpc.ServerOption
opts = append(opts, opt)
server := grpc.NewServer(opts...)
proto.RegisterServerServer(server, &Server{})
lis, err := net.Listen("tcp", "0.0.0.0:15001")
if err != nil {
panic("服务端监听失败-->" + err.Error())
}
err = server.Serve(lis)
if err != nil {
panic("服务端开启服务失败-->" + err.Error())
}
}