redis实现多次操作失败封禁ip
2022-05-10 本文已影响0人
谁把月亮涂黑啦
项目中有时会有这样的需求:用户多次登录失败即锁定客户端ip,防止爆破,这个用redis就可以实现了(其他kv数据库也行),细节如下:
示例采用nodejs实现,其他语言同理
async ipInspect(body) {
const { accumulate = true } = body || {}
// nginx 需设置header
let ip = this.ctx.request.get('X-Real-IP')
// 本地环境
if (this.config.env === 'local') {
ip = this.ctx.ip.includes('::1') ? '127.0.0.1' : this.ctx.ip
}
// 这里以应用名称为例
const name = this.app.config.name
// 存储此ip的计数
let key = `${name}_${ip}`
// 锁定时间
let lockSeconds = 60 * 5
// 锁定key
let lock_key = `${name}_dura_${ip}`
// 获取计数
const count = await this.app.redis.get(key)
// 获取剩余过期时间
let lock_ttl = await this.app.redis.ttl(lock_key)
// key计数大于5并且lock_key不存在时设置lock_key,保证封禁时间内lock_key有效
if (count && count >= 4 && lock_ttl < -1) {
await this.app.redis.set(lock_key, 1, 'EX', lockSeconds)
lock_ttl = lockSeconds
}
// lock_key存在时返回剩余锁定时间
if (lock_ttl >= -1) {
const remain_time = Math.ceil(lock_ttl / 60)
return remain_time
}
// accumulate为true时才累加key的值
if (accumulate) {
// 自增 1
await this.app.redis.incr(key)
// 设置过期时间,ttl 单位为秒
await this.app.redis.expire(key, 60 * 1)
}
return false
}