美文网首页
nginx_lua 跳转验证码

nginx_lua 跳转验证码

作者: Daisy小朋友 | 来源:发表于2020-01-14 11:31 被阅读0次

一 Nginx加载Lua环境

默认情况下Nginx不支持Lua模块, 需要安装LuaJIT解释器, 并且需要重新编译Nginx

1.环境准备

[root@nginx ~]# yum -y install gcc gcc-c++ make pcre-devel zlib-devel openssl-devel

2.下载最新的luajit和ngx_devel_kit以及lua-nginx-module

[root@nginx ~]# mkdir -p /soft/src && cd /soft/src
[root@nginx ~]# wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz
[root@nginx ~]# wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz
[root@nginx~]#wget https://github.com/openresty/lua-nginx-module/archive/v0.10.13.tar.gz

3.解压ngx_devel_kit和lua-nginx-module

//解压后为ngx_devel_kit-0.2.19
[root@nginx ~]# tar xf v0.2.19.tar.gz 
//解压后为lua-nginx-module-0.9.16
[root@nginx ~]# tar xf v0.10.13.tar.gz

4.安装LuaJIT Luajit是Lua即时编译器。

[root@nginx ~]# tar zxvf LuaJIT-2.0.3.tar.gz 
[root@nginx ~]# cd LuaJIT-2.0.3
[root@nginx ~]# make && make install

5.安装Nginx并加载模块(下载对应nginx版本并查看安装模块,在安装模块基础上增加安装的两个模块)

[root@nginx ~]# cd /soft/src
[root@nginx ~]# wget http://nginx.org/download/nginx-1.12.2.tar.gz
[root@nginx ~]# tar xf nginx-1.12.2.tar.gz
[root@nginx~]# 
./configure--prefix=/nginx
--add-module=/soft/src/ngx_devel_kit-0.2.19 --add-module=/soft/src/lua-nginx-module-0.10.13
[root@nginx ~]# make -j2 && make install
//建立软链接, 不建立会出现share object错误
ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
//4.加载lua库,加入到ld.so.conf文件
echo "/usr/local/LuaJIT/lib" >> /etc/ld.so.conf
ldconfig

二 lua连接redis

下载redis.lua 放到相应文件夹中,如/usr/local/nginx/lua
并在nginx的http层添加一行
如:/usr/local/nginx/conf/nginx.conf
lua_package_path "/usr/local/nginx/lua/redis.lua";
重启nginx即可

三 添加配置文件

1 /usr/local/nginx/lua 上传写好的access.lua脚本
2 修改www.conf 添加一行
access_by_lua_file /usr/local/nginx/lua/access.lua;
3 重启nginx即可

四 access.lua脚本重点

需修改字段:
1 时间
--禁封ip时间--
ip_bind_time = 60
--ip访问时间频率时间段--
ip_time_out = 30
--ip访问频率最大值--
connect_count = 15
2 redis连接的IP端口密码
3 需要跳转的验证码页面连接

条件:在30s中如果访问超过15次跳转验证码
跳转回原页面:1 滑动验证码 2等待60s后(禁封时间解除)
access.lua脚本

--禁封ip时间--
ip_bind_time = 60
--ip访问世家频率时间段--
ip_time_out = 30    
--ip访问频率最大值--
connect_count = 15
-- 禁封时间中,30s内访问50次旧验证码--

--clientIP获取真实IP--
clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
    clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
     clientIP = ngx.var.remote_addr
end

--判断只对详情页生效---
local source1=ngx.var.scheme.."://"..ngx.var.host..ngx.var.request_uri
--local m, err = ngx.re.match(source1, "(auctionListNew|tmallIndexNew|transEnprsNew|qitaIndexNew|shopsGet|auctionGet)-.*\.(html|do|action)")
--source1, err = red:lpush("source1",m)

--正则匹配--
local m, err = ngx.re.match(source1, "(auctionListNew|tmallIndexNew|transEnprsNew|qitaIndexNew|shopsGet|auctionGet)")
--sourice1, err = red:lpush("source1",source1)
if m == nil then
   goto B
end



--连接redis--
local redis = require "resty.redis"
local red = redis:new()
local ok, err = red:connect("your redis IP", 6379)
ok, err = red:auth("your passwd")
red:set_timeout(1000) 

--local source2=ngx.var.scheme.."://"..ngx.var.host..ngx.var.request_uri
--source2, err = red:lpush("source2",source2)--
--ngx.log(ngx.INFO, " string:", str)

--如果连接不成功直接退出---
if not ok then

    goto A

end

--达到条件,跳转验证码页面---
is_bind, err = red:get("bind:"..ngx.var.remote_addr)

if is_bind == '1' then
    local source=ngx.encode_base64(ngx.var.scheme.."://"..ngx.var.host..ngx.var.request_uri)
    local client=ngx.encode_base64(clientIP)   
    local dest="验证码url".."?u="..source.."A5PA0"..client
    ngx.redirect(dest,302)
   
    goto A
  
end

--记录开始时间和次数---
start_time, err = red:get("time:"..ngx.var.remote_addr)
ip_count, err = red:get("count:"..ngx.var.remote_addr)

 
--如果开始时间为空或者时间已经大于禁封时间,redis中记录---
if start_time == ngx.null or os.time() - start_time > ip_time_out then

    res, err = red:set("time:"..ngx.var.remote_addr , os.time())
    res, err = red:expire("time:"..ngx.var.remote_addr, ip_bind_time)
    res, err = red:set("count:"..ngx.var.remote_addr , 1)
    res, err = red:expire("count:"..ngx.var.remote_addr, ip_bind_time)
else

    ip_count = ip_count + 1

    res, err = red:incr("count:"..ngx.var.remote_addr)

    if ip_count >= connect_count then

        res, err = red:set("bind:"..ngx.var.remote_addr, 1)

        res, err = red:expire("bind:"..ngx.var.remote_addr, ip_bind_time)

    end

end

::A::

local ok, err = red:close()

::B::

lua连接redis脚本

local sub = string.sub
local byte = string.byte
local tcp = ngx.socket.tcp
local null = ngx.null
local type = type
local pairs = pairs
local unpack = unpack
local setmetatable = setmetatable
local tonumber = tonumber
local tostring = tostring
local rawget = rawget
local select = select
--local error = error


local ok, new_tab = pcall(require, "table.new")
if not ok or type(new_tab) ~= "function" then
    new_tab = function (narr, nrec) return {} end
end


local _M = new_tab(0, 55)

_M._VERSION = '0.27'


local common_cmds = {
    "get",      "set",          "mget",     "mset",
    "del",      "incr",         "decr",                 -- Strings
    "llen",     "lindex",       "lpop",     "lpush",
    "lrange",   "linsert",                              -- Lists
    "hexists",  "hget",         "hset",     "hmget",
    --[[ "hmset", ]]            "hdel",                 -- Hashes
    "smembers", "sismember",    "sadd",     "srem",
    "sdiff",    "sinter",       "sunion",               -- Sets
    "zrange",   "zrangebyscore", "zrank",   "zadd",
    "zrem",     "zincrby",                              -- Sorted Sets
    "auth",     "eval",         "expire",   "script",
    "sort"                                              -- Others
}


local sub_commands = {
    "subscribe", "psubscribe"
}


local unsub_commands = {
    "unsubscribe", "punsubscribe"
}


local mt = { __index = _M }


function _M.new(self)
    local sock, err = tcp()
    if not sock then
        return nil, err
    end
    return setmetatable({ _sock = sock, _subscribed = false }, mt)
end


function _M.set_timeout(self, timeout)
    local sock = rawget(self, "_sock")
    if not sock then
        error("not initialized", 2)
        return
    end

    sock:settimeout(timeout)
end


function _M.set_timeouts(self, connect_timeout, send_timeout, read_timeout)
    local sock = rawget(self, "_sock")
    if not sock then
        error("not initialized", 2)
        return
    end

    sock:settimeouts(connect_timeout, send_timeout, read_timeout)
end


function _M.connect(self, host, port_or_opts, opts)
    local sock = rawget(self, "_sock")
    if not sock then
        return nil, "not initialized"
    end

    local unix

    do
        local typ = type(host)
        if typ ~= "string" then
            error("bad argument #1 host: string expected, got " .. typ, 2)
        end

        if sub(host, 1, 5) == "unix:" then
            unix = true
        end

        if unix then
            typ = type(port_or_opts)
            if port_or_opts ~= nil and typ ~= "table" then
                error("bad argument #2 opts: nil or table expected, got " ..
                      typ, 2)
            end

        else
            typ = type(port_or_opts)
            if typ ~= "number" then
                port_or_opts = tonumber(port_or_opts)
                if port_or_opts == nil then
                    error("bad argument #2 port: number expected, got " ..
                          typ, 2)
                end
            end

            if opts ~= nil then
                typ = type(opts)
                if typ ~= "table" then
                    error("bad argument #3 opts: nil or table expected, got " ..
                          typ, 2)
                end
            end
        end

    end

    self._subscribed = false

    local ok, err

    if unix then
        ok, err = sock:connect(host, port_or_opts)
        opts = port_or_opts

    else
        ok, err = sock:connect(host, port_or_opts, opts)
    end

    if not ok then
        return ok, err
    end

    if opts and opts.ssl then
        ok, err = sock:sslhandshake(false, opts.server_name, opts.ssl_verify)
        if not ok then
            return ok, "failed to do ssl handshake: " .. err
        end
    end

    return ok, err
end


function _M.set_keepalive(self, ...)
    local sock = rawget(self, "_sock")
    if not sock then
        return nil, "not initialized"
    end

    if rawget(self, "_subscribed") then
        return nil, "subscribed state"
    end

    return sock:setkeepalive(...)
end


function _M.get_reused_times(self)
    local sock = rawget(self, "_sock")
    if not sock then
        return nil, "not initialized"
    end

    return sock:getreusedtimes()
end


local function close(self)
    local sock = rawget(self, "_sock")
    if not sock then
        return nil, "not initialized"
    end

    return sock:close()
end
_M.close = close


local function _read_reply(self, sock)
    local line, err = sock:receive()
    if not line then
        if err == "timeout" and not rawget(self, "_subscribed") then
            sock:close()
        end
        return nil, err
    end

    local prefix = byte(line)

    if prefix == 36 then    -- char '$'
        -- print("bulk reply")

        local size = tonumber(sub(line, 2))
        if size < 0 then
            return null
        end

        local data, err = sock:receive(size)
        if not data then
            if err == "timeout" then
                sock:close()
            end
            return nil, err
        end

        local dummy, err = sock:receive(2) -- ignore CRLF
        if not dummy then
            return nil, err
        end

        return data

    elseif prefix == 43 then    -- char '+'
        -- print("status reply")

        return sub(line, 2)

    elseif prefix == 42 then -- char '*'
        local n = tonumber(sub(line, 2))

        -- print("multi-bulk reply: ", n)
        if n < 0 then
            return null
        end

        local vals = new_tab(n, 0)
        local nvals = 0
        for i = 1, n do
            local res, err = _read_reply(self, sock)
            if res then
                nvals = nvals + 1
                vals[nvals] = res

            elseif res == nil then
                return nil, err

            else
                -- be a valid redis error value
                nvals = nvals + 1
                vals[nvals] = {false, err}
            end
        end

        return vals

    elseif prefix == 58 then    -- char ':'
        -- print("integer reply")
        return tonumber(sub(line, 2))

    elseif prefix == 45 then    -- char '-'
        -- print("error reply: ", n)

        return false, sub(line, 2)

    else
        -- when `line` is an empty string, `prefix` will be equal to nil.
        return nil, "unknown prefix: \"" .. tostring(prefix) .. "\""
    end
end


local function _gen_req(args)
    local nargs = #args

    local req = new_tab(nargs * 5 + 1, 0)
    req[1] = "*" .. nargs .. "\r\n"
    local nbits = 2

    for i = 1, nargs do
        local arg = args[i]
        if type(arg) ~= "string" then
            arg = tostring(arg)
        end

        req[nbits] = "$"
        req[nbits + 1] = #arg
        req[nbits + 2] = "\r\n"
        req[nbits + 3] = arg
        req[nbits + 4] = "\r\n"

        nbits = nbits + 5
    end

    -- it is much faster to do string concatenation on the C land
    -- in real world (large number of strings in the Lua VM)
    return req
end


local function _do_cmd(self, ...)
    local args = {...}

    local sock = rawget(self, "_sock")
    if not sock then
        return nil, "not initialized"
    end

    local req = _gen_req(args)

    local reqs = rawget(self, "_reqs")
    if reqs then
        reqs[#reqs + 1] = req
        return
    end

    -- print("request: ", table.concat(req))

    local bytes, err = sock:send(req)
    if not bytes then
        return nil, err
    end

    return _read_reply(self, sock)
end


local function _check_subscribed(self, res)
    if type(res) == "table"
       and (res[1] == "unsubscribe" or res[1] == "punsubscribe")
       and res[3] == 0
   then
        self._subscribed = false
    end
end


function _M.read_reply(self)
    local sock = rawget(self, "_sock")
    if not sock then
        return nil, "not initialized"
    end

    if not rawget(self, "_subscribed") then
        return nil, "not subscribed"
    end

    local res, err = _read_reply(self, sock)
    _check_subscribed(self, res)

    return res, err
end


for i = 1, #common_cmds do
    local cmd = common_cmds[i]

    _M[cmd] =
        function (self, ...)
            return _do_cmd(self, cmd, ...)
        end
end


for i = 1, #sub_commands do
    local cmd = sub_commands[i]

    _M[cmd] =
        function (self, ...)
            self._subscribed = true
            return _do_cmd(self, cmd, ...)
        end
end


for i = 1, #unsub_commands do
    local cmd = unsub_commands[i]

    _M[cmd] =
        function (self, ...)
            local res, err = _do_cmd(self, cmd, ...)
            _check_subscribed(self, res)
            return res, err
        end
end


function _M.hmset(self, hashname, ...)
    if select('#', ...) == 1 then
        local t = select(1, ...)

        local n = 0
        for k, v in pairs(t) do
            n = n + 2
        end

        local array = new_tab(n, 0)

        local i = 0
        for k, v in pairs(t) do
            array[i + 1] = k
            array[i + 2] = v
            i = i + 2
        end
        -- print("key", hashname)
        return _do_cmd(self, "hmset", hashname, unpack(array))
    end

    -- backwards compatibility
    return _do_cmd(self, "hmset", hashname, ...)
end


function _M.init_pipeline(self, n)
    self._reqs = new_tab(n or 4, 0)
end


function _M.cancel_pipeline(self)
    self._reqs = nil
end


function _M.commit_pipeline(self)
    local reqs = rawget(self, "_reqs")
    if not reqs then
        return nil, "no pipeline"
    end

    self._reqs = nil

    local sock = rawget(self, "_sock")
    if not sock then
        return nil, "not initialized"
    end

    local bytes, err = sock:send(reqs)
    if not bytes then
        return nil, err
    end

    local nvals = 0
    local nreqs = #reqs
    local vals = new_tab(nreqs, 0)
    for i = 1, nreqs do
        local res, err = _read_reply(self, sock)
        if res then
            nvals = nvals + 1
            vals[nvals] = res

        elseif res == nil then
            if err == "timeout" then
                close(self)
            end
            return nil, err

        else
            -- be a valid redis error value
            nvals = nvals + 1
            vals[nvals] = {false, err}
        end
    end

    return vals
end


function _M.array_to_hash(self, t)
    local n = #t
    -- print("n = ", n)
    local h = new_tab(0, n / 2)
    for i = 1, n, 2 do
        h[t[i]] = t[i + 1]
    end
    return h
end


-- this method is deperate since we already do lazy method generation.
function _M.add_commands(...)
    local cmds = {...}
    for i = 1, #cmds do
        local cmd = cmds[i]
        _M[cmd] =
            function (self, ...)
                return _do_cmd(self, cmd, ...)
            end
    end
end


setmetatable(_M, {__index = function(self, cmd)
    local method =
        function (self, ...)
            return _do_cmd(self, cmd, ...)
        end

    -- cache the lazily generated method in our
    -- module table
    _M[cmd] = method
    return method
end})


return _M

相关文章

  • nginx_lua 跳转验证码

    一 Nginx加载Lua环境 默认情况下Nginx不支持Lua模块, 需要安装LuaJIT解释器, 并且需要重新...

  • 6. 写文章功能

    1.思考 验证码过期 点击验证码60码的按钮的禁用问题? 下一个按钮 注册成功后,页面跳转问题 新用户跳转 文章的...

  • 写文章

    验证码过期点击验证码60码的按钮的禁用问题?下一个按钮注册成功后,页面跳转问题新用户跳转 文章的三种内容没有图,一...

  • 【Android 开发-kotlin】手机号验证登录demo

    运行效果 输入手机号,自动发送验证码 输入错误验证码自动清空 输入正确验证码自动跳转至其他页面 内容简概 一、搭建...

  • 9 简阅项目 写文章功能

    验证码过期点击验证码60码的按钮的禁用问题?下一个按钮注册成功后,页面跳转问题新用户跳转文章的三种内容没有图,一到...

  • 用户中心

    路由,跳转登录页,填写登录信息(用户名(昵称,手机,邮箱),密码,验证码),

  • 记一个安全测试问题

    app有一个忘记密码功能,流程如下 用户点击忘记密码---跳转至获取验证码页面获取并输入验证码---进入设置页面设...

  • 安卓手机验证码验证页面

    本篇文章主要介绍暑假期间实现的手机验证码验证页面主要知识点: 手机号登录页面实现 验证码验证页面实现 页面跳转 验...

  • android 中 自己实现验证码表格填写的效果

    项目中,遇到了这样要求:实现6位验证码填写的效果,验证码是数字,输入一个后自动跳转到下一个,然后可以删除回退,界面...

  • 漏洞挖掘之爆破的艺术

    oxo1 暴力破解偶遇302跳转 在进行暴力破解登录框的时候、发现第一个验证码是正常的、后面全部验证码错误、查看3...

网友评论

      本文标题:nginx_lua 跳转验证码

      本文链接:https://www.haomeiwen.com/subject/dtwkactx.html