feat(ca): 认证独立化 CA 模块 v1.0.0 + gateway v0.9.0 纯转发瘦身
拓扑:waf:443 → ca:8443(认证+前置转发)→ gateway:8445(仅 loopback 纯转发), WAF upstream 不变,core/dnfs2/前端零改动。 ca v1.0.0(新模块): - 认证资产逐字搬迁自 gateway v0.8.0(9 条认证路由、Token 双轨吊销、 PBKDF2、限流、WS 代理鉴权、wrapperHttp、优雅关闭) - handleForward 前置转发层:固定上游 gateway:8445;无 Target-Url 公开直转, 有则本地验签后注入 X-Auth-User/X-Auth-Admin/Authorization(strip-then-set) - is_special_header 新增剥离 x-auth-user/x-auth-admin;上游不可达统一 502 - confs/configs/ca.ini 新增([Upstream] gateway + UPSTREAM_GATEWAY env) gateway v0.9.0(2470→约 560 行): - 删除全部认证代码,退居 127.0.0.1:8445 - 启动 loopback 强制自检(非 loopback 拒绝启动) - X-Auth-User 存在性不变量:显式 Target-Url 无该头一律 401 - gateway.ini 精简至 [Server]/[Proxy]/[Downstream db] 验收:黑盒 34 断言对 8443 原样全绿(32 passed/2 skipped,与基线一致); 探针实测伪造 X-Auth-User 经 CA 被剥离(echo 实证)、直连 8445 无头 401、 白名单外 403、gateway 宕机 CA 502。core/init.txt 加入 ca/_run.sh。
This commit is contained in:
1 parent
bbea1ee9d8
commit
407ce3c366
19 files changed
+3991
-2523
No files matched your search
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
namespace qing {
|
||||
|
||||
class LocalTime {
|
||||
public:
|
||||
// 获取当前本地时间字符串
|
||||
static std::string getCurrent(const std::string& format = "%Y-%m-%d %H:%M:%S") {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t t = std::chrono::system_clock::to_time_t(now);
|
||||
std::tm tm_buf{};
|
||||
localtime_r(&t, &tm_buf);
|
||||
char buf[128];
|
||||
std::strftime(buf, sizeof(buf), format.c_str(), &tm_buf);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
// 解析时间字符串为 system_clock::time_point(本地时间 → UTC)
|
||||
static std::optional<std::chrono::system_clock::time_point> parse(
|
||||
const std::string& str,
|
||||
const std::string& format = "%Y-%m-%d %H:%M:%S"
|
||||
) {
|
||||
std::tm tm_buf{};
|
||||
std::istringstream iss{str};
|
||||
iss >> std::get_time(&tm_buf, format.c_str());
|
||||
if (iss.fail()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
// mktime 将本地时间转换为 time_t(UTC)
|
||||
std::time_t t = std::mktime(&tm_buf);
|
||||
if (t == -1) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::chrono::system_clock::from_time_t(t);
|
||||
}
|
||||
|
||||
// ----- 过期判断 -----
|
||||
static bool isExpired(const std::chrono::system_clock::time_point& tp) {
|
||||
return std::chrono::system_clock::now() > tp;
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
static bool isExpired(const std::chrono::system_clock::time_point& tp,
|
||||
const std::chrono::duration<Rep, Period>& gracePeriod) {
|
||||
return std::chrono::system_clock::now() > tp + gracePeriod;
|
||||
}
|
||||
|
||||
static bool isExpired(const std::string& timeStr,
|
||||
const std::string& format = "%Y-%m-%d %H:%M:%S") {
|
||||
auto parsed = parse(timeStr, format);
|
||||
if (!parsed) return true;
|
||||
return isExpired(*parsed);
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
static bool isExpired(const std::string& timeStr,
|
||||
const std::chrono::duration<Rep, Period>& gracePeriod,
|
||||
const std::string& format = "%Y-%m-%d %H:%M:%S") {
|
||||
auto parsed = parse(timeStr, format);
|
||||
if (!parsed) return true;
|
||||
return isExpired(*parsed, gracePeriod);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user