local core = require("apisix.core") local redis = require("resty.redis") local _M = {} function _M.access(conf, ctx) -- 确保在请求阶段执行 if not ngx or not ngx.var then core.log.warn("Not in request context, skipping auth check") return end -- ========== 获取请求头 ========== local headers = ngx.req.get_headers() local user_key = headers["Authorization"] local service_code = headers["Authorization-Type"] local req_auth = headers["Authorization-Auth"] local refresh = headers["Refresh"] local request_uri = ngx.var.uri -- ========== 获取 Redis 配置 ========== local redis_config = core.config.local_conf().redis or {} local redis_host = redis_config.host or "127.0.0.1" local redis_port = redis_config.port or 6379 local redis_password = redis_config.password or "" local redis_db = redis_config.db or 0 -- ========== 参数校验 ========== if not user_key or user_key == "" then core.log.warn("Missing Authorization header") return core.response.exit(401, { code = 10003, message = "未登录", data = nil }) end if not service_code or service_code == "" then core.log.warn("Missing Authorization-Type header") return core.response.exit(401, { code = 10003, message = "未登录", data = nil }) end -- ========== 构建Redis Key ========== local redis_key = "login:service:" .. service_code .. ":" .. user_key -- ========== Redis连接 ========== local red = redis:new() red:set_timeouts(1000, 1000, 1000) local ok, err = red:connect(redis_host, redis_port) if not ok then core.log.error("Redis connect error: ", err) red:set_keepalive(10000, 100) return core.response.exit(500, { code = 10003, message = "系统错误,请稍后重试", data = nil }) end -- Redis认证 if redis_password and redis_password ~= "" then local auth_ok, auth_err = red:auth(redis_password) if not auth_ok then core.log.error("Redis auth error: ", auth_err) red:set_keepalive(10000, 100) return core.response.exit(500, { code = 10003, message = "系统错误,请稍后重试", data = nil }) end end -- 选择数据库 if redis_db and redis_db > 0 then red:select(redis_db) end -- ========== 获取用户信息 ========== local res, err = red:get(redis_key) red:set_keepalive(10000, 100) if err then core.log.error("Redis get error: ", err) return core.response.exit(500, { code = 10003, message = "系统错误,请稍后重试", data = nil }) end if not res or res == ngx.null then core.log.warn("User not found in redis, key: ", redis_key) return core.response.exit(401, { code = 10003, message = "未登录或登录已过期", data = nil }) end -- ========== 解析用户信息 ========== local json, decode_err = core.json.decode(res) if not json then core.log.error("JSON decode error: ", decode_err, " data: ", res) return core.response.exit(500, { code = 10003, message = "数据解析错误", data = nil }) end -- ========== Admin路径权限校验 ========== if service_code == "admin1" then if not req_auth or req_auth == "" then core.log.warn("Missing Authorization-Auth header for admin") return core.response.exit(403, { code = 10008, message = "没有权限访问该资源", data = nil }) end local roles = json.roles or {} local expect_path = roles[req_auth] if not expect_path or expect_path == "" then core.log.error("Permission not found for auth: ", req_auth, " user_id: ", json.id, " roles: ", core.json.encode(roles)) return core.response.exit(403, { code = 10008, message = "没有权限访问该资源", data = nil }) end local full_expect_uri = "/" .. expect_path if request_uri ~= full_expect_uri then local is_prefix_match = false if expect_path:sub(-1) == "*" then local base_path = expect_path:sub(1, -2) if request_uri:find(base_path, 1, true) == 1 then is_prefix_match = true end end if not is_prefix_match then core.log.error("URI mismatch - request: ", request_uri, " expected: ", full_expect_uri, " auth: ", req_auth, " user_id: ", json.id) return core.response.exit(403, { code = 10008, message = "没有权限访问该资源", data = nil }) end end end -- ========== 向下游透传用户信息 ========== if json.id then ngx.req.set_header("X-User-Id", tostring(json.id)) end if json.name then ngx.req.set_header("X-User-Name", json.name) end if json.username then ngx.req.set_header("X-Username", json.username) end ngx.req.set_header("X-Refresh", refresh ) ngx.req.set_header("X-Service-Code", service_code) return end return _M