You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:19:58