Go Gin设置并从中间件访问上下文值

问题描述 投票:0回答:1

我试图在中间件中设置用户上下文,然后尝试检查用户是否具有其他处理程序功能的权限。但是由于某种原因,当我尝试从上下文访问用户时,它返回为nil。中间件代码似乎正在工作,当我传递有效的jwt令牌时,它表明用户是在中间件功能的上下文中设置的。但是,一旦我点击getCurrentUser函数,它就会显示为无。

这里是代码:中间件

// Middleware wraps the request with auth middleware
func Middleware(path string, sc *cfg.Server, orm *orm.ORM) gin.HandlerFunc {
    logger.Info("[Auth.Middleware] Applied to path: ", path)
    return gin.HandlerFunc(func(c *gin.Context) {
        t, err := ParseToken(c, sc)
        if err != nil {
            authError(c, err)
        } else {
            if claims, ok := t.Claims.(jwt.MapClaims); ok {
                if claims["exp"] != nil {
                    issuer := claims["iss"].(string)
                    userid := claims["jti"].(string)
                    email := claims["email"].(string)
                    if claims["aud"] != nil {
                        audiences := claims["aud"].(interface{})
                        logger.Warnf("\n\naudiences: %s\n\n", audiences)
                    }
                    if claims["alg"] != nil {
                        algo := claims["alg"].(string)
                        logger.Warnf("\n\nalgo: %s\n\n", algo)
                    }
                    if user, err := orm.FindUserByJWT(email, issuer, userid); err != nil {
                        authError(c, ErrForbidden)
                    } else {
                        if user != nil {
                            c.Request = addToContext(c, consts.ProjectContextKeys.UserCtxKey, user)
                            logger.Debug("User: ", user.ID)
                        }
                        c.Next()
                    }
                } else {
                    authError(c, ErrMissingExpField)
                }
            } else {
                authError(c, err)
            }
        }
    })
}

路线

// User routes
func User(sc *cfg.Server, r *gin.Engine, orm *orm.ORM) error {
    // OAuth handlers
    mw := auth.Middleware(sc.VersionedEndpoint("/user/:id"), sc, orm)
    g := r.Group(sc.VersionedEndpoint("/user"))
    g.Use(mw)
    g.GET("/:id", mw, user.Get(orm))
    g.PUT("/:id", mw, user.Update(orm))
    g.POST("/", user.Create(orm))

    return nil
}

handler

func Get(orm *orm.ORM) gin.HandlerFunc {
    return func(ctx *gin.Context) {
        cu := getCurrentUser(ctx)
        if ok, err := cu.HasPermission(consts.Permissions.Create, consts.EntityNames.Users); !ok || err != nil {
            ctx.String(http.StatusUnauthorized, "BAD")
        }
    }
}

addToContext:

func addToContext(c *gin.Context, key consts.ContextKey, value interface{}) *http.Request {
    return c.Request.WithContext(context.WithValue(c.Request.Context(), key, value))
}

getCurrentUser:

func getCurrentUser(ctx context.Context) *dbm.User {
    cu := ctx.Value(utils.ProjectContextKeys.UserCtxKey).(*dbm.User)
    logger.Debugf("currentUser: %s - %s", cu.Email, cu.ID)
    return cu
}
rest go jwt handler gin
1个回答
1
投票

问题是您将用户存储在一个上下文中,但是随后您尝试从另一个上下文中检索用户。值*gin.Context和值*gin.Context.Request.Context是两个单独的上下文值。

您正在使用请求的上下文来存储用户:

c.Request.WithContext(context.WithValue(c.Request.Context(), key, value))

然后您使用gin上下文来检索用户:

func getCurrentUser(ctx context.Context) *dbm.User {
    cu := ctx.Value(utils.ProjectContextKeys.UserCtxKey).(*dbm.User)
    // ...

func Get(orm *orm.ORM) gin.HandlerFunc {
    return func(ctx *gin.Context) {
        cu := getCurrentUser(ctx) // here you're passing *gin.Context to the function.
        // ...

因此,为了解决该问题,将传递给getCurrentUser调用的值更改为:

func Get(orm *orm.ORM) gin.HandlerFunc {
    return func(ctx *gin.Context) {
        cu := getCurrentUser(ctx.Request.Context())
        if ok, err := cu.HasPermission(consts.Permissions.Create, consts.EntityNames.Users); !ok || err != nil {
            ctx.String(http.StatusUnauthorized, "BAD")
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.