nginx+lua+redis实现验证码防采集

之前介绍过在nginx里如何嵌入lua模块,利用nginx+lua可以很好的开发开发nginx的业务逻辑,并且达到高并发的效果。

下面我们就来介绍下利用nginx+lua+redis实现防采集的功能。

现象:

网站在为用户提供服务的同时也在被搜索引擎、采集器不断的抓取,可能会造成网站不堪重负,导致页面放回5XX错误。针对此种情况,我们就要对采集器及搜索引擎来进行访问控制,当然对搜索引擎的控制可能会影响网站的收录。

功能描述:

nginx+lua在前端实现客户端的访问控制,将客户端的访问信息记入redis中,如果超过访问频率的限制,则跳转到php生成的验证码界面;若验证通过则可以继续访问半小时,若验证不通过则被封锁半小时。由于采集器的ip可能变化,所以在此不会一直封锁。

1.nginx_lua模块安装

请参考前面“nginx和lua”的博文http://blog.csdn.net/yanggd1987/article/details/46679989

2.lua-resty-redis模块安装

cd /usr/local/src
wget https://github.com/openresty/lua-resty-redis/archive/master.zip
unzip master.zip
cd lua-resty-redis-master
mkdir -p /usr/local/nginx/lua
#将lib拷贝到nginx安装目录下的lua文件夹内
cp -rf lib /usr/local/nginx/lua
cd /usr/local/nginx/lua/lib
ln -s redis.lua resty/redis.lua

3.在nginx目录下编写lua脚本

cd /usr/local/src
wget https://github.com/openresty/lua-resty-redis/archive/master.zip
unzip master.zip
cd lua-resty-redis-master
mkdir -p /usr/local/nginx/lua
#将lib拷贝到nginx安装目录下的lua文件夹内
cp -rf lib /usr/local/nginx/lua
cd /usr/local/nginx/lua/lib
ln -s redis.lua resty/redis.lua

cd /usr/local/nginx/lua
vim access_test.lua
package.path = "/usr/local/nginx/lua/?.lua;/usr/local/nginx/lua/lib/?.lua;"
package.cpath = "/usr/local/nginx/lua/?.so;/usr/local/nginx/lua/lib/?.so;"
--封禁ip时间
ip_bind_time = 300
--ip访问频率时间段
ip_time_out = 60
--ip访问频率计数最大值
connect_count = 60
--连接redis
local redis = require "resty.redis"
local cache = redis.new()
local ok ,err = cache.connect(cache,"10.10.10.8","6381")
cache:set_timeout(60000)

--如果连接失败,跳转到label处
if not ok then
        goto label
end

--ip封禁key
is_bind , err = cache:get("bind_"..ngx.var.remote_addr)

--白名单
--验证码通过后,只需将white_ngx.var.remote_addr置为1并设置过期时间即可,在下次访问时将不会再做判断
is_white , err = cache:get("white_"..ngx.var.remote_addr)

if tonumber(is_white) == 1 then
        goto label
end

--查询ip是否在封禁时间段内,若在则跳转到验证码页面
if tonumber(is_bind) == 1 then
        --ngx.say("block,跳转到验证码页")
        --base64编码
        local source=ngx.encode_base64(ngx.var.scheme.."://"..ngx.var.host..ngx.var.request_uri)
        local dest="http://10.10.10.8/authcode.html".."?continue="..source
        --url_args编码
        --local source=ngx.encode_args({continue=ngx.var.scheme.."://"..ngx.var.host..ngx.var.request_uri})
        --local dest="http://10.10.10.8/authcode.html".."?"..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)
        if ip_count >= connect_count then
                res , err = cache:set("bind_"..ngx.var.remote_addr , 1)
                --以下步骤交给php,若验证码不通过则设置bind过期时间,若验证码通过则设置white_ip为1并且设置其过期时间
                --res , err = cache:expire("bind_"..ngx.var.remote_addr , ip_bind_time)
        end
end

::label::
local ok , err = cache:close()

10.10.10.8/authcode.html为验证码页面,需要其他语言编写,在此就不再说了!

注意:

1.在生产环境中由于后端php需要记录远程客户端ip,因此需要在nginx代理上开启相关设置:

proxy_set_header   X-Real-IP        $remote_addr;

proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

2.在应用生产环境中可能是多域名环境,ngx.exec和ngx.redirect的跳转方式不同,ngx.exec为内部跳转,ngx.redirect为外部跳转;

3.white_ip为白名单,若验证成功则添加白名单,并且设置白名单的过期时间;若验证不成功,则直接设置bind_ip的过期时间;若不验证,则会一直被封锁;

4.判断white_ip一定要放在bind_ip上面,因为验证已经添加白名单后则会直接跳过后续判断部分;

5.在跳转到验证码页面后,需要记录所要访问页面的url,以达到验证通过后跳转到所要访问的页面;

6.在访问时间内没有达到限制次数,则cout_ip和time_ip会被重置。

4.将lua脚本添加到相应的location下

   location /test {
                access_by_lua_file '/usr/local/nginx1.6/lua/access.lua';
                content_by_lua 'ngx.header.content_type = "text/plain"
                ngx.say("hello,world")
                ';
        }

在1分钟内,当访问次数达到100,就会跳转到验证码界面。

ps:在此感谢zengbin3013(http://blog.csdn.net/zengbin3013/article/details/9313979)博主,本脚本也是在他的基础上改的。

参考内容:

https://github.com/openresty/lua-resty-redis

https://github.com/openresty/lua-nginx-module

http://wiki.nginx.org/HttpLuaModule

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-25 00:15:49

nginx+lua+redis实现验证码防采集的相关文章

nginx+lua+redis(openresty)配置

nginx+lua+redis(openresty)配置 2014-07-18 11:10 2494人阅读 评论(1) 收藏 举报 方案一: 1.安装lua解释器 wget http://luajit.org/download/LuaJIT-2.0.2.tar.gz (http://luajit.org/download.html) 配置lua Lib和include/luajit-$version目录为环境变量 2.下载ngx_devel_kit和lua-nginx-module https:

nginx lua redis 访问频率限制(转)

1. 需求分析 Nginx来处理访问控制的方法有多种,实现的效果也有多种,访问IP段,访问内容限制,访问频率限制等. 用Nginx+Lua+Redis来做访问限制主要是考虑到高并发环境下快速访问控制的需求. Nginx处理请求的过程一共划分为11个阶段,分别是: post-read.server-rewrite.find-config.rewrite.post-rewrite. preaccess.access.post-access.try-files.content.log. 在openre

nginx+lua+redis构建高并发应用(转)

nginx+lua+redis构建高并发应用 ngx_lua将lua嵌入到nginx,让nginx执行lua脚本,高并发,非阻塞的处理各种请求. url请求nginx服务器,然后lua查询redis,返回json数据. 备注:centos或者redhat系统请跳转到nginx + ngx_lua安装测试 一.安装lua 1 2 3 # apt-get install lua5.1 # apt-get install liblua5.1-dev # apt-get install liblua5.

Nginx+Lua+Redis 对请求进行限制

Nginx+Lua+Redis 对请求进行限制 一.概述 需求:所有访问/myapi/**的请求必须是POST请求,而且根据请求参数过滤不符合规则的非法请求(黑名单), 这些请求一律不转发到后端服务器(Tomcat) 实现思路:通过在Nginx上进行访问限制,通过Lua来灵活实现业务需求,而Redis用于存储黑名单列表. 相关nginx上lua或redis的使用方式可以参考我之前写的一篇文章: openresty(nginx).lua.drizzle调研 http://www.cnblogs.c

nginx+php+redis vs nginx+lua+redis

最近在做通知系统,前端用的轮询方式(后端压力不小),因为时间比较紧,开始我准备把未读通知标识存在数据库中,但是每次拿数据的时候需要查询一遍数据库,总监说你这样效率较低,说你可以根据用户id作为key放在redis中存储.说说自己在做这个的一些体会和闲下来总结的一些笔记. phpredis connect pconnect 我最开始使用的是connect,每次请求完毕关闭连接 1 <?php 2 $redis = new Redis(); 3 $nError = $redis->connect(

Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Discuz!

Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Discuz! log.latermoon.com/

Nginx+Lua+Redis配置

想在Nginx上开发具有这样功能的一个转发模块,外部转发策略控制服务器将一些指定的URL发送给数据库,Nginx读取数据库中的URL列表,将列表指定的这些URL转发到特定的缓存代理服务器上,其他非数据库URL列表中的URL请求直接通过Nginx转发到出口网关上.实际上以上的功能就是很多网站利用Nginx做负载均衡时的实现的七层转发功能,不太一样的是,我想加一个外部的转发策略控制服务器将一些实时的URL列表发送给Nginx,这样如果这些URL信息是根据大数据处理结果统计出的最高热点访问URL,就可

nginx+lua+redis构建高并发应用

ngx_lua将lua嵌入到nginx,让nginx执行lua脚本,高并发,非阻塞的处理各种请求. url请求nginx服务器,然后lua查询redis,返回json数据. 一.安装lua-nginx-module 参见<LNMLGC>架构 二.安装redis2-nginx-module模块 get https://github.com/openresty/echo-nginx-module get https://github.com/openresty/redis2-nginx-modul

nginx+lua+redis实现灰度发布_test

nginx+lua+redis实现灰度发布: 灰度发布是指在黑白之间能够平滑过渡的一种方式 AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面 来.灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现.调整问题,以保证其影响度. 灰度发布可以保证应用系统的稳定,降低产品升级影响的用户范围:也可以按照一定的策略让部分用户提前参与产品测试,从而提早获取到用户的反馈,完善应用功能 原理:使用ngi