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
}
上一篇 下一篇

猜你喜欢

热点阅读