【问题标题】:gRPC authorization approachgRPC 授权方式
【发布时间】:2019-06-23 12:59:15
【问题描述】:

我从事 go grpc 服务并实施授权。从字面上看,必须根据 JWT 声明允许或禁止访问 gprc 方法。

我在 grpc.UnaryServerInterceptor 级别进行 JWT 解析 - 提取声明并使用值填充上下文,如果没有 jwt 或它不正确,则未经身份验证。

func (s *Server) GetSomething(ctx context.Context, req *GetSomething Request) (*GetSomething Response, error) {
    if hasAccessTo(ctx, req.ID) {
        //some work here
    }
}

func hasAccessTo(ctx context.Context, string id) {
    value := ctx.Value(ctxKey).(MyStruct)
    //some work here

}

所以我想知道是否有一些常见的授权/身份验证做法来避免每个 grpc 服务器方法中的样板代码?

【问题讨论】:

  • 也许go-kit 的架构可以帮助您构建服务。
  • 我见过类似的东西,样板被放在一个库中,为处理函数提供一个包装函数。然后是一种策略系统,每个端点都定义了所需的权限,这些权限被映射到一个角色(基于来自 JWT 的身份声明)。
  • 如果您要保护每个呼叫,那么可以使用UnaryInterceptor。如果您需要一个可行的示例,我可以提供一个示例
  • @Varcorb 如果你能发布它会很好
  • 这里有一个 oauth 示例可能会有所帮助:github.com/grpc/grpc-go/tree/master/examples/features/…

标签: authentication go authorization jwt grpc


【解决方案1】:

如果您想在每个请求上验证 jwt,您可以像这样调用 UnaryInterceptor

// middleware for each rpc request. This function verifies the client has the correct "jwt".
func authInterceptor(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    meta, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        return nil, status.Error(codes.Unauthenticated, "INTERNAL_SERVER_ERROR")
    }
    if len(meta["jwt"]) != 1 {
        return nil, status.Error(codes.Unauthenticated, "INTERNAL_SERVER_ERROR")
    }

    // if code here to verify jwt is correct. if not return nil and error by accessing meta["jwt"][0]

    return handler(ctx, req) // go to function.
}

在来自客户端的context 中,使用metadata 传递jwt 字符串并进行验证。

在你的主函数中记得像这样注册它

// register server
myService := grpc.NewServer(
    grpc.UnaryInterceptor(authInterceptor), // use auth interceptor middleware
)
pb.RegisterTheServiceServer(myService, &s)
reflection.Register(myService)

您的客户需要像这样调用您的服务器:

// create context with token and timeout
ctx, cancel := context.WithTimeout(metadata.NewOutgoingContext(context.Background(), metadata.New(map[string]string{"jwt": "myjwtstring"})), time.Second*1)
defer cancel()

【讨论】:

  • 谢谢,我在拦截器中的做法几乎相同。但我正在寻找一种更高级的方法,然后只需检查是否有jwt。我正在寻找某种授权:是否允许用户使用该方法
  • @SergiiGetman - 他的回答忽略了传递给函数的*grpc.UnaryServerInfo,但它包含我认为对您的目的有用的信息。例如,它有一个 .FullMethod 属性,可以让您对每个方法执行不同的授权逻辑。
猜你喜欢
  • 2019-04-17
  • 2023-03-30
  • 1970-01-01
  • 2018-11-21
  • 1970-01-01
  • 2018-11-05
  • 2015-01-21
  • 2022-08-24
  • 2021-10-17
相关资源
最近更新 更多