Access Control
整体逻辑 :基于 group_ip 获取规则组,白名单或黑名单的模式匹配请求上下文,获取访问控制结果
规则管理器 manager模块化提供 ,匹配时提供核心方法
function get_rules(group_id):基于group_id获取的规则列表方法function get_value_func(rule): 基于rule自生获取对应的 function设计的
operator为function时,会寻找规则中的 方法规则进行匹配方法规则的设计目的是为了,对于规则中无法通过简单的字符串匹配的场景,实现更复杂的匹配
function get_internal_function(rule): 基于rule自生获取对应的内置 function设计的
operator为@function时,会寻找规则中的 内置方法规则进行匹配内置方法规则的设计目的是为了,提供一些常用的匹配方法,方便用户直接使用
local _M = {}
local ac_utils = require("lua_modules.http_req.access_control.ac_utils")
-- 匹配规则
-- @param field_val 字段值
-- @param operator 操作符
-- @param value 规则值
-- @param rule 规则本身,可以适配更多复杂场景
-- @param manager 可选的存储对象,默认为 rules_manager
-- @return boolean 是否匹配
local function match_rule(field_val, operator, value, rule, manager)
if not field_val or not operator then
return false
end
-- 方法,获取方法函数
if operator == "function" then
-- 获取计算值的函数
local value_func, err = ac_utils.get_value_func(rule, manager)
if not value_func then
ngx.log(ngx.ERR, "failed to get function rule: ", err or "unknown error")
return false
end
if type(value_func) ~= "function" then
ngx.log(ngx.ERR, "value_func must be a function when operator is 'function'")
return false
end
-- 调用函数并确保返回布尔值
local ok, res = pcall(value_func, field_val)
if not ok then
return false
end
if type(res) ~= "boolean" then
return false
end
return res
end
-- 方法,获取内置的方法
if operator == "@function" then
local func, err = ac_utils.get_internal_function(rule, manager)
if not func then
ngx.log(ngx.ERR, "failed to get function: ", err or "unknown error")
return false
end
if type(func) ~= "function" then
ngx.log(ngx.ERR, "func must be a function when operator is '@function'")
return false
end
-- 调用函数并确保返回布尔值
local ok, res = pcall(func, field_val)
if not ok then
return false
end
if type(res) ~= "boolean" then
return false
end
return res
end
--一些通用的操作符
if operator == "equals" then
return field_val == value
elseif operator == "not_equals" then
return field_val ~= value
elseif operator == "prefix" then
return field_val:sub(1, #value) == value
elseif operator == "suffix" then
return field_val:sub(-#value) == value
elseif operator == "contains" then
return field_val:find(value, 1, true) ~= nil
elseif operator == "regex" then
return ngx.re.find(field_val, value, "jo") ~= nil
elseif operator == "in" then
-- 支持逗号分隔字符串或 table
if type(value) == "string" then
for v in value:gmatch("[^,]+") do
if field_val == v then
return true
end
end
elseif type(value) == "table" then
for _, v in ipairs(value) do
if field_val == v then
return true
end
end
end
return false
else
-- 未知操作符
return false
end
end
-- 核心检查函数
-- 白名单检查是只要有一条规则命中就放行
-- 黑名单检查是只要有一条规则命中就拒绝
-- @param ctx 请求上下文
-- @param rules 规则列表 一个规则示例 {field="host", operator="equals", value="example.com", effect="deny"}
-- @param mode 检查模式 "whitelist" 或 "blacklist"
-- @param manager 可选的规则管理器,默认为 rules_manager
-- @return boolean 是否允许通过
local function check_ctx(ctx, rules, mode, manager)
mode = mode or "blacklist"
for _, rule in ipairs(rules) do
local field_val = ctx[rule.field] -- 获取指定字段的值
if field_val and match_rule(field_val, rule.operator, rule.value, rule, manager) then
if mode == "blacklist" and rule.effect == "deny" then
return false
elseif mode == "whitelist" and rule.effect == "allow" then
return true
end
end
end
-- 如果没有任何规则命中
if mode == "blacklist" then
return true -- 默认放行
else
return false -- 默认拒绝
end
end
-- 通用检查函数
-- @param ctx 请求上下文
-- @param rules 规则列表
-- @param mode 检查模式 "whitelist" 或 "blacklist"
-- @param manager 可选的规则管理器,默认为 rules_manager
-- @return boolean 是否允许通过
function _M.check_ctx(ctx, rules, mode, manager)
return check_ctx(ctx, rules, mode, manager)
end
-- 白名单检查
-- 只要有一条规则命中就放行
-- @param ctx 请求上下文
-- @param rules 规则列表
-- @param manager 可选的规则管理器,默认为 rules_manager
-- @return boolean 是否允许通过
function _M.check_ctx_whitelist(ctx, rules, manager)
return check_ctx(ctx, rules, "whitelist", manager)
end
-- 黑名单检查
-- 只要有一条规则命中就拒绝
-- @param ctx 请求上下文
-- @param rules 规则列表
-- @param manager 可选的规则管理器,默认为 rules_manager
-- @return boolean 是否允许通过
function _M.check_ctx_blacklist(ctx, rules, manager)
return check_ctx(ctx, rules, "blacklist", manager)
end
return _M
27 January 2026