如何在gRPC Gateway中配置公开路由与认证路由?
在gRPC Gateway中配置公开与认证路由
完全可以实现类似Echo框架的路由分组认证逻辑,不过gRPC Gateway的实现方式和Echo略有不同,下面给你两种可行方案:
方案一:拆分gRPC Gateway Mux,通过主路由分发
这种方式适合将整个gRPC服务拆分为公开服务和需要认证的服务,分别注册到不同的Mux,再通过标准库的http.ServeMux做路由分发:
func run() error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())} // 1. 创建公开路由的Mux publicMux := runtime.NewServeMux() // 注册不需要认证的gRPC服务到publicMux err := gw.RegisterPublicServiceHandlerFromEndpoint(ctx, publicMux, *grpcServerEndpoint, opts) if err != nil { return err } // 2. 创建需要认证的Mux,并包装认证中间件 authMux := runtime.NewServeMux() // 注册需要认证的gRPC服务到authMux err = gw.RegisterPrivateServiceHandlerFromEndpoint(ctx, authMux, *grpcServerEndpoint, opts) if err != nil { return err } // 给authMux加上认证中间件 authHandler := middlewares.Verify(authMux) // 3. 创建主路由分发器 mainMux := http.NewServeMux() // 公开路由前缀映射到publicMux mainMux.Handle("/public/", http.StripPrefix("/public", publicMux)) // 认证路由前缀映射到带中间件的authHandler mainMux.Handle("/private/", http.StripPrefix("/private", authHandler)) // 启动HTTP服务器 return http.ListenAndServe(":8081", mainMux) }
方案二:单一Mux结合路径判断中间件
如果你的gRPC服务里既有公开接口又有需要认证的接口,不想拆分服务,可以给主Mux添加全局中间件,在中间件里根据请求路径判断是否需要认证:
func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 定义需要认证的路径前缀(根据你的gRPC Gateway生成的路径调整) authPaths := []string{"/api/v1/private/", "/api/v1/user/"} for _, path := range authPaths { if strings.HasPrefix(r.URL.Path, path) { // 执行认证逻辑 if err := middlewares.VerifyToken(r); err != nil { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } break } } // 不需要认证或认证通过,继续处理请求 next.ServeHTTP(w, r) }) } func run() error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux() opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())} err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux, *grpcServerEndpoint, opts) if err != nil { return err } // 给主Mux包装认证中间件 wrappedMux := authMiddleware(mux) // 启动HTTP服务器 return http.ListenAndServe(":8081", wrappedMux) }
关于你的设想的说明
你提到的直接给authenMux加认证再注册服务的方式,会导致该服务下所有路由都强制走认证,如果你的服务里只有需要认证的接口,这种方式是可行的;但如果服务混合了公开和认证接口,就需要用上面两种方案来区分。
内容的提问来源于stack exchange,提问作者onemin
相关产品推荐
相关产品推荐

