从goauth2的一个bug提及

goauth2因为做者使用诡计,致使若是goauth2启用redis缓存token与code后,致使android客户端不能在获取token了,这里就分享一下查这个bug的过程。android

首先,bug的表现为获取token失败,具体的缘由是由于当goauth2产生了token与code后,可是只能存储code而不能存储token,这样验证的时候因为没法从redis服务器获取token,因此就失败了,客户端就没法访问受保护的资源了。redis

func (ac *RedisAuthCache) RegisterAccessToken(clientID, scope, token string) (ttype string, expiry int64, err error) {
    
    vars := map[string]string{
        "clientID": clientID,
        "scope":    scope,
    }
    val, err := json.Marshal(vars)
    if err != nil {
        log.Println("Error Marshalling variables for Redis Set", err)
        return "", 0, err
    }

    key := tokenKey(token)

    err = ac.db.Set(key, val)
    if err != nil {
        log.Println("Error performing Redis-Set", err)
        return "", 0, err
    }

    valid, err := ac.db.Expire(key, int64(ac.TokenExpiry))
    if err != nil {
        log.Println("Error performing Redis-Expire", err)
        return "", 0, err
    } else if !valid {
        err = errors.New("Invalid return from setting code expiration.")
        log.Println("Error performing Redis-Expire", err)
        return "", 0, err
    }

    return "bearer", ac.TokenExpiry, nil
}

我最早怀疑的是究竟是key不能设置仍是token不能设置,所以作了几种尝试,ac.db.Set("token:257fc9823289eaabc4a28aff190b59b468bffb53", val)拿上一次产生的token三硬编码,发现能够设置;但若是函数调用时用一样的key就不能设置;因而当取回tokenKey后,我就破坏key,发现这个key就能设置,这完全让我迷惑了,因而怀疑是goauth使用的redis有问题,又换了一种redis,但是问题依旧。无语了,灵感一现,注意到set了token后,就设置了Expire,会不会是这行代码致使没法设置token,果断注释代码,发现token就保存住了,一会儿就猜想bug缘由,会不会是设置了Expire,这个是负责token的超时,若是超时设置成了0,那么刚设置完token,又立刻告诉redis token的超时为0,因此就消失了,再看源码json

func NewRedisAuthCacheWithClient(addr string, dbnum int, pass string) *RedisAuthCache {
    return &RedisAuthCache{
        db:          redis.New(addr, dbnum, pass),
        CodeExpiry:  260,
        TokenExpiry: 0,
    }
}

果真,TokenExpiry默认为0。缓存

我为何要特别说明这个问题呢,由于严格来讲做者并无写错任何一行代码,TokenExpiry给予一个保守的默认值,做者也没有错,但是这些没有错加在一块儿就成全了这个bug。这个bug很是有趣的地方在于,比如redis是个箱子,程序逻辑一半是往箱子里放苹果,而另外一个逻辑就是吃掉这个苹果,但是咱们却疑问苹果去那了?最后redis躺枪,咱们怪redis这个怪物偷吃了苹果。服务器

相关文章
相关标签/搜索