实现限制访问频率插件

一)创建limit_frequency插件

在plugins目录下新建limit_frequency目录,代表插件名称;并在其目录下新建handler.lua

handler.lua

---------------------handler.lua-----------------------
local utils = require("fago.common.utils")
local redis = require("fago.lib.redis")  --引入redis模块
local BasePlugin = require("fago.plugins.base_plugin")

local opts = {
    ip = "192.168.31.247",
    port = "6379",
    db_index = 0
}

local LimitFrequencyHandler = BasePlugin:extend()
LimitFrequencyHandler.PRIORITY = 1

function LimitFrequencyHandler:new()
    LimitFrequencyHandler.super.new(self, "LimitFrequency-plugin")
    utils.debug_log("===========LimitFrequencyHandler.new============");
end


function LimitFrequencyHandler:access()
    LimitFrequencyHandler.super.access(self)
    utils.debug_log("===========LimitFrequencyHandler.access============");
    
    local user_ip = utils.get_ip();
    
    local key = "limit:frequency:"..user_ip;

    local red = redis:new(opts)  --创建一个对象,注意是用冒号调用的
    
    --得到此客户端IP的频次
    local resp, err = red:get(key)
    
    if err then
        return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis 获取值失败
    end 

    if resp == nil then   
        utils.debug_log("===========key set ============");
        local result,err = red:set(key, 1) -- 单位时间 第一次访问
        utils.debug_log("===========key expire ============");
        result,err = red:expire(key, 10) --10秒时间 过期
    end  

    if type(resp) == "string" then 
        if tonumber(resp) > 10 then -- 超过10次
            return ngx.exit(ngx.HTTP_FORBIDDEN) --直接返回403
        end
    end

    --调用API设置key  
    local ok, err = red:incr(key)  
    if err then
        return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis 报错 
    end 

end

return LimitFrequencyHandler;

二)在主入口fago.lua中access阶段进行改造

Last updated

Was this helpful?