美文网首页
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 跳转验证码

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