github.com/gin-contrib/sessions 连接redis无法传用户名修改
出现问题:
在Gin框架中,我们可以依赖gin-contrib/sessions中间件处理session,redis作为存储引擎,如下
import(
"github.com/boj/redistore"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/redis"
)
...
r := gin.Default()
store, err := redis.NewStoreWithDB(10, "tcp", "redis host", "redis password", "redis db", []byte("secret"))
if err != nil {
log.Fatalf("[fatal] %s\n", err)
}
r.Use(sessions.Sessions("mysession", store))
在 Redis 6.0 及以上版本中,Redis 引入了 ACL(Access Control List)功能,支持用户管理和认证,连接redis可以使用如下方式
redis-cli
> AUTH myuser mypassword
但该包没有提供用户名密码的连接方式,github上有相关提问但暂未解决
解决方案
1.更换存储引擎
2.临时重新连接redis的验证方法
import(
"github.com/boj/redistore"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/redis"
redigo "github.com/gomodule/redigo/redis"
)
...
r := gin.Default()
storeBase, err := NewRediStoreWithDB(10, "tcp", "redis host", "redis username", "redis password", "redis db", []byte("secret"))
if err != nil {
log.Fatalf("[fatal] %s\n", err)
}
redisStore := &store{storeBase}
r.Use(sessions.Sessions("mysession", store))
type store struct {
*redistore.RediStore
}
func (c *store) Options(options sessions.Options) {
c.RediStore.Options = options.ToGorillaOptions()
}
func NewRediStoreWithDB(size int, network, address, username, password, DB string, keyPairs ...[]byte) (*redistore.RediStore, error) {
return redistore.NewRediStoreWithPool(&redigo.Pool{
MaxIdle: size,
IdleTimeout: 240 * time.Second,
TestOnBorrow: func(c redigo.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
},
Dial: func() (redigo.Conn, error) {
return dialWithDB(network, address, username, password, DB)
},
}, keyPairs...)
}
func dialWithDB(network, address, username, password, DB string) (redigo.Conn, error) {
c, err := dial(network, address, username, password)
if err != nil {
return nil, err
}
if _, err := c.Do("SELECT", DB); err != nil {
c.Close()
return nil, err
}
return c, err
}
func dial(network, address, username, password string) (redigo.Conn, error) {
c, err := redigo.Dial(network, address)
if err != nil {
return nil, err
}
if password != "" && username == "" {
if _, err := c.Do("AUTH", password); err != nil {
c.Close()
return nil, err
}
}
if password != "" && username != "" {
if _, err := c.Do("AUTH", username, password); err != nil {
c.Close()
return nil, err
}
}
return c, err
}