Go语言实战案例-Redis实现用户登录次数限制
在登录功能中,如果不加限制,攻击者可能会通过 暴力破解 尝试大量密码组合,带来安全风险。
一个常见解决方案是:在一定时间内限制用户的登录尝试次数,超过次数就锁定一段时间。
Redis 的高性能和天然的过期机制,非常适合实现这种登录限流功能。本文将通过 Go + Redis 实现一个 用户登录次数限制 示例。
一、场景说明
- • 规则:每个用户 1 分钟内最多尝试登录 5 次
- • 超过限制:锁定 1 分钟,不允许继续登录
- • 实现方式:
- • 登录时,在 Redis 中维护一个计数器
- • 如果计数器超过阈值,就禁止登录
二、环境准备
安装依赖:
go get github.com/redis/go-redis/v9
确保本地或 Docker 中已运行 Redis:
docker run -d -p 6379:6379 redis
三、Redis 工具初始化
package mainimport ("context""fmt""github.com/redis/go-redis/v9""log""time"
)var ctx = context.Background()
var rdb *redis.Clientfunc initRedis() {rdb = redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})if _, err := rdb.Ping(ctx).Result(); err != nil {log.Fatal("Redis 连接失败:", err)}log.Println("Redis 连接成功")
}
四、实现登录次数限制
// CheckLoginLimit 检查用户是否超过登录限制
func CheckLoginLimit(username string) bool {key := fmt.Sprintf("login:%s", username)limit := 5 // 最大尝试次数blockTime := time.Minute // 超过限制后锁定时间// 自增计数器count, err := rdb.Incr(ctx, key).Result()if err != nil {log.Println("Redis 错误:", err)return false}if count == 1 {// 第一次设置过期时间rdb.Expire(ctx, key, blockTime)}if count > int64(limit) {return false // 超过限制}return true
}
五、模拟用户登录逻辑
// MockLogin 模拟登录
func MockLogin(username, password string) {if !CheckLoginLimit(username) {log.Printf("用户 %s 登录失败: 尝试次数过多,请稍后再试\n", username)return}// 假设正确密码是 "123456"if password == "123456" {log.Printf("用户 %s 登录成功\n", username)// 成功后清除计数器rdb.Del(ctx, fmt.Sprintf("login:%s", username))} else {log.Printf("用户 %s 登录失败: 密码错误\n", username)}
}
六、测试效果
func main() {initRedis()for i := 1; i <= 7; i++ {MockLogin("alice", "wrongpass")}
}
运行结果:
用户 alice 登录失败: 密码错误
用户 alice 登录失败: 密码错误
用户 alice 登录失败: 密码错误
用户 alice 登录失败: 密码错误
用户 alice 登录失败: 密码错误
用户 alice 登录失败: 尝试次数过多,请稍后再试
用户 alice 登录失败: 尝试次数过多,请稍后再试
七、总结
通过本案例,我们实现了:
- • 使用 Redis 存储用户登录尝试次数
- • 借助
INCR
+EXPIRE
实现自动计数和过期清理 - • 登录成功时清除计数器,避免误封
✅ 应用场景:
- • 登录安全限制(防止暴力破解)
- • API 请求限流
- • 手机验证码发送频率控制