大家好,最新在学习golang, 阅读了一个开源框架(gin-vue-admin)
基于锻炼的目的实现了一个jwt+redis白名单功能,主要包含了登录覆盖,踢人等
希望各位不吝赐教,帮忙点评一下,指出一些问题和隐患。
```go
package utils
import (
"cc-admin/global"
"context"
"time"
)
// 白名单模式(登录接口做限流和验证码)
// 登录、续签操作都会添加到redis中
// 如果重启服务器会丢失(可以实现持久化)
// 考虑到前端并发请求,旧的token会有5s的使用时间
type RedisJwt struct {
oldTokenExpiresAt time.Duration // 旧token过期时间
oldTokenExpiresImmediately bool // 旧的token是否立即过期
ctx context.Context
}
var (
JwtCache = NewJwtCache()
)
func NewJwtCache() *RedisJwt {
return &RedisJwt{
oldTokenExpiresAt: time.Second * 5,
oldTokenExpiresImmediately: false,
ctx: context.Background(),
}
}
// 获取redis缓存中的jwt
func (r *RedisJwt) GetJwt(username string) (token string, err error) {
token, err = global.REDIS.Get(r.ctx, username).Result()
return
}
// 缓存token
func (r *RedisJwt) SetJwt(username, token string) error {
expiresAt, _ := time.ParseDuration(global.CONFIG.Jwt.ExpiresAt)
// 旧的token如何处理
if !r.oldTokenExpiresImmediately {
oldToken, err := r.GetJwt(username)
if err == nil && oldToken != token {
global.REDIS.Set(r.ctx, oldToken, username, r.oldTokenExpiresAt)
}
}
return global.REDIS.Set(r.ctx, username, token, expiresAt).Err()
}
// 强制用户退出
func (r *RedisJwt) Logout(username string) error {
return global.REDIS.Del(r.ctx, username).Err()
}
// 会在jwt中间件中验证是否合法
// 失效的token无法通过
func (r *RedisJwt) Validate(username, jwtStr string) (ok bool, err error) {
// 旧的token如何处理
if !r.oldTokenExpiresImmediately {
u, err := global.REDIS.Get(r.ctx, jwtStr).Result()
if err == nil && u == username {
return true, nil
}
}
token, err := r.GetJwt(username)
if err != nil {
// redis获取token失败
return
}
ok = (token == jwtStr)
return
}
```
有疑问加站长微信联系(非本文作者)