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上有相关提问但暂未解决

https://github.com/gin-contrib/sessions/issues/264

解决方案

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
}
posted @ 2024-10-28 16:08  元気田支店长  阅读(35)  评论(0编辑  收藏  举报