白名单域名:硬编码 https://qs***.me 、https://www.qs***.me ,加两个本地开发域名(127.0.0.1:8443、localhost:8443)。

动态回填 Origin:仅当请求 Origin 命中白名单时才设置 Access-Control-Allow-Origin,否则不返回该头(浏览器会拒绝跨域请求)。
追加 Vary: Origin:告诉缓存该响应因 Origin 而异,避免缓存误用。
移除 Access-Control-Allow-Credentials: true:当前用 Bearer token(请求头),非 cookie,不需要此头;保留反而增加风险面。
This commit is contained in:
qing committed 2026-07-25 10:22:58 +08:00
1 parent a9e50bb598
commit 3d8cf52503
1 file changed
+22 -1
+22 -1
View File
@@ -506,7 +506,28 @@ void registerRoutes(HttpServer &server) {
server.options("*", [](const auto& req, const auto& params) {
pmc::net::http::response<pmc::net::http::string_body> res;
res.result(pmc::net::http::status::ok);
res.set(pmc::net::http::field::access_control_allow_origin, "*");
// CORS 白名单(P1-4):仅允许官方域名,防止任意网站跨域调用
// 原配置 Access-Control-Allow-Origin: * 过宽,XSS 拿到 token 后可跨域读取数据
// 动态回填 Origin:仅当请求 Origin 命中白名单时才返回该值,否则不返回 ACAO 头
static const std::vector<std::string> allowed_origins = {
"https://qsont.me",
"https://www.qsont.me",
"http://127.0.0.1:8443", // 本地开发调试
"http://localhost:8443"
};
auto origin_it = req.base().find("Origin");
if (origin_it != req.base().end()) {
std::string origin = std::string(origin_it->value());
for (const auto& allowed : allowed_origins) {
if (origin == allowed) {
res.set(pmc::net::http::field::access_control_allow_origin, origin);
res.set(pmc::net::http::field::vary, "Origin");
break;
}
}
}
res.set(pmc::net::http::field::access_control_allow_methods, "GET, POST, OPTIONS");
res.set(pmc::net::http::field::access_control_allow_headers, "Content-Type, Authorization");
res.set(pmc::net::http::field::access_control_max_age, "86400");