Go Настройка джина и доступ к значению контекста из промежуточного программного обеспечения - PullRequest
0 голосов
/ 01 марта 2020

Я пытаюсь установить свой пользовательский контекст в промежуточном программном обеспечении, затем пытаюсь проверить, есть ли у пользователя разрешение на другие функции обработчика. Но по какой-то причине, когда я пытаюсь получить доступ к пользователю из контекста, он возвращается как ноль. Код промежуточного программного обеспечения, кажется, работает, когда я передаю действительный токен jwt, он показывает, что пользователь настраивается в контексте в функции промежуточного программного обеспечения. Но как только я нажимаю на функцию getCurrentUser, она говорит, что это ноль.

Вот код: Middleware

// 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
}

обработчик

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
}

1 Ответ

1 голос
/ 02 марта 2020

Проблема в том, что вы сохраняете пользователя в одном контексте, но затем пытаетесь извлечь пользователя из другого контекста. Значение *gin.Context и значение *gin.Context.Request.Context являются двумя отдельными значениями контекста.

Вы используете контекст запроса для хранения пользователя:

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

И затем вы используете контекст джина для извлечения пользователя:

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")
        }
    }
}
...