zoukankan      html  css  js  c++  java
  • 高频访问IP弹验证码架构图 让被误伤的用户能及时自行解封的策略

    高频访问IP限制 --Openresty(nginx + lua) [反爬虫之旅] - Silbert Monaphia - CSDN博客 https://blog.csdn.net/qq_29245097/article/details/77461719

    我不准备在web应用中做ip的统计和查封,应用就应该只做业务功能,这些基础东西应该由我们应用的前部——专业的Nginx实现

    Nginx本身就有根据ip访问频率的设置,比如“服务器访问频率限制和IP限制”就有提到。不过Nginx只能强硬地返回个403状态码什么的,但是我们这次ip封禁时间比较久,那么如果误伤到用户,我们仅仅强硬地返回个403,用户将会毫无办法证明自己是人,然后要等很久,那就伤用户就伤得很深了,因此我们需要一种可以让被误伤的用户能及时自行解封的策略,验证码就是一个不错的选择,可是Nginx该怎么接入验证码呢?

    -anti_spider
      -conf/
         -nginx.conf
      -lua/
         -access.lua
      -log/
         -error.log
      -geetest_web/
         -demo/
         -sdk/
         -geetest.py
         -setup.py
         -requirements.txt
    

      

    
    
    worker_processes  1;
    error_log logs/error.log;
    events {
        worker_connections 1024;
    }
    http {
        server {
            listen 80;
            location / {
                access_by_lua_file 'lua/access.lua';
                content_by_lua 'ngx.say("Welcome PENIS!")';
            }
        }
    }

    access.lua

    -- package.path = '/usr/local/openresty/nginx/lua/?.lua;/usr/local/openresty/nginx/lua/lib/?.lua;'
    -- package.cpath = '/usr/local/openresty/nginx/lua/?.so;/usr/local//openresty/nginx/lua/lib/?.so;'
    
    -- 连接redis
    local redis = require 'resty.redis'
    local cache = redis.new()
    local ok ,err = cache.connect(cache,'127.0.0.1','6379')
    cache:set_timeout(60000)
    -- 如果连接失败,跳转到label处
    if not ok then
      goto label
    end
    
    -- 白名单
    is_white ,err = cache:sismember('white_list', ngx.var.remote_addr)
    if is_white == 1 then
      goto label
    end
    
    -- 黑名单
    is_black ,err = cache:sismember('black_list', ngx.var.remote_addr)
    if is_black == 1 then
      ngx.exit(ngx.HTTP_FORBIDDEN)
      goto label
    end
    
    
    -- ip访问频率时间段
    ip_time_out = 60
    -- ip访问频率计数最大值
    connect_count = 45
    -- 60s内达到45次就ban
    
    -- 封禁ip时间(加入突曲线增长算法)
    ip_ban_time, err = cache:get('ip_ban_time:' .. ngx.var.remote_addr)
    if ip_ban_time == ngx.null then
      ip_ban_time = 300
      res , err = cache:set('ip_ban_time:' .. ngx.var.remote_addr, ip_ban_time)
      res , err = cache:expire('ip_ban_time:' .. ngx.var.remote_addr, 43200) -- 12h重置
    end
    
    
    -- 查询ip是否在封禁时间段内,若在则跳转到验证码页面
    is_ban , err = cache:get('ban:' .. ngx.var.remote_addr) 
    if tonumber(is_ban) == 1 then
      -- source携带了之前用户请求的地址信息,方便验证成功后返回原用户请求地址
      local source = ngx.encode_base64(ngx.var.scheme .. '://' ..
        ngx.var.host .. ':' .. ngx.var.server_port .. ngx.var.request_uri)
      local dest = 'http://127.0.0.1:5000/' .. '?continue=' .. source 
      ngx.redirect(dest,302)
      goto label
    end
    
    -- ip记录时间key
    start_time , err = cache:get('time:' .. ngx.var.remote_addr)
    -- ip计数key
    ip_count , err = cache:get('count:' .. ngx.var.remote_addr)
    
    -- 如果ip记录时间的key不存在或者当前时间减去ip记录时间大于指定时间间隔,则重置时间key和计数key
    -- 如果当前时间减去ip记录时间小于指定时间间隔,则ip计数+1,
    -- 并且ip计数大于指定ip访问频率,则设置ip的封禁key为1,同时设置封禁key的过期时间为封禁ip时间
    
    if start_time == ngx.null or os.time() - tonumber(start_time) > ip_time_out then
      res , err = cache:set('time:' .. ngx.var.remote_addr , os.time())
      res , err = cache:set('count:' .. ngx.var.remote_addr , 1)
    else
      ip_count = ip_count + 1
      res , err = cache:incr('count:' .. ngx.var.remote_addr)
      -- 统计当日访问ip集合
      res , err = cache:sadd('statistic_total_ip:' .. os.date('%x'), ngx.var.remote_addr)
      if ip_count >= connect_count then
        res , err = cache:set('ban:' .. ngx.var.remote_addr , 1)
        res , err = cache:expire('ban:' .. ngx.var.remote_addr , ip_ban_time)
        res , err = cache:incrby('ip_ban_time:' .. ngx.var.remote_addr, ip_ban_time)
        -- 统计当日屏蔽ip总数
        res , err = cache:sadd('statistic_ban_ip:' .. os.date('%x'), ngx.var.remote_addr)
      end
    end
    
    ::label::
    local ok , err = cache:close()
    

      

  • 相关阅读:
    【事件类】雅思口语
    【人物类】雅思口语
    【物品类】雅思口语
    Cassandra (二)Java | scala操作
    rpm安装在哪里了?
    用IDEA创建springboot项目遇到的问题Plugin 'org.springframework.boot:spring-boot-maven-plugin:' not found
    JDBC连接mysql出现The server time zone value '�й���׼ʱ��' is unrecognized
    Java反射、注解
    Junit单元测试
    Java-线程池、匿名内部类、Lambda表达式
  • 原文地址:https://www.cnblogs.com/rsapaper/p/10005524.html
Copyright © 2011-2022 走看看