如何为gRPC方法添加标签区分公私方法并在拦截器中读取?
gRPC方法自定义权限标签与拦截器实现
我需要给gRPC方法添加标签来区分私有/公共方法,不用命名规则来区分,而是通过自定义Option标记,然后在拦截器里根据这个标签实现权限校验逻辑——私有方法必须经过授权才能访问,公共方法直接放行。
1. 定义自定义MethodOption
首先在proto文件里扩展google.protobuf.MethodOptions,添加一个自定义的私有方法标记字段,注意自定义字段号要在50001-99999的预留区间内:
import "google/protobuf/descriptor.proto"; extend google.protobuf.MethodOptions { // 标记方法是否为私有,需要授权访问 optional bool private = 50006; }
2. 在gRPC服务方法中使用自定义Option
在定义服务方法时,给需要私有访问的方法加上(private) = true的option,公共方法可以不设置(默认视为公共):
message ItemData { int32 id = 1; string title = 2; string description = 3; float price = 4; string currency = 5; int32 owner_id = 6; int32 category_id = 7; } message GetItemsRequest { int32 category_id = 1; string title = 2; } message GetItemsResponse { repeated ItemData items = 1; } message CreateItemRequest { ItemData item = 1; } message CreateItemResponse { ItemData item = 1; } service ItemsService{ rpc GetItems(GetItemsRequest) returns (GetItemsResponse){ option (google.api.http) = { get: "/v1/get-items" }; // 未标记private,默认是公共方法 } rpc GetMyItems(GetItemsRequest) returns (GetItemsResponse){ option (private) = true; // 标记为私有方法 } rpc CreateItem(CreateItemRequest) returns (CreateItemResponse){ option (private) = true; // 标记为私有方法 } }
3. 在拦截器中读取自定义Option并实现校验
以Go语言为例,在拦截器里通过方法描述符获取自定义的private标记,然后执行对应的授权逻辑:
import ( "context" "google.golang.org/grpc" "google.golang.org/protobuf/descriptor" yourproto "your/proto/package/path" // 替换为你的proto生成的包路径 ) func AuthInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { // 从方法信息中获取描述符 methodDesc := info.MethodInfo.MethodDescriptor // 获取自定义的private option privateExt := methodDesc.Options().(*descriptor.MethodOptions).GetExtension(yourproto.E_Private) // 转换为bool类型并判断 if isPrivate, ok := privateExt.(bool); ok && isPrivate { // 私有方法,执行授权校验 if err := authorize(ctx); err != nil { return nil, err } } // 公共方法或授权通过,执行原方法逻辑 return handler(ctx, req) } // 示例授权函数,根据实际业务实现 func authorize(ctx context.Context) error { // 这里写你的授权逻辑,比如从ctx中获取token验证身份 return nil }
如果是其他语言(如Java、Python),核心逻辑一致:从gRPC方法的描述符Options中取出自定义扩展字段,判断标记后执行对应逻辑。
内容的提问来源于stack exchange,提问作者Kevin Bogdan
相关产品推荐
相关产品推荐

