WordPress或PHP覆盖Access-Control-Allow-Origin致NIP-05验证失败
背景
我正在开发WordPress插件wp-nostr-nip05,用来实现Nostr NIP-05认证,需要把access-control-allow-origin设为*。之前用静态nostr.json文件搭配Apache/Nginx配置access-control-allow-origin: '*'时完全正常。
现在改成插件实现后,nostr.json变成了启用force-type的PHP脚本,可以通过HTTP_HOST和登录名从用户表匹配对应NIP-05 ID。现在访问网站根目录或者/.well-known目录时能拿到预期的响应头,但访问/.well-known/nostr.json时,响应头出了问题:
access-control-allow-methods: POST, GET, OPTIONS access-control-allow-origin: https://example.com, * access-control-max-age: 1728000
不是预期的access-control-allow-origin: *,我觉得这就是多个NIP-05客户端(astral.ninja、Damus)验证失败的原因,只有snort.social能正常验证。
已尝试的无效操作
- 注释WordPress核心文件里设置该响应头的代码
- 安装专门设置响应头的插件
- 直接在
nostr.json脚本里加Header("Access-Control-Allow-Origin: *"); - 确认服务器没有
.htaccess覆盖配置的情况
诊断工具结果不一致
- 在线CORS测试工具显示上面的异常响应头
wget命令返回的响应头里Access-Control-Allow-Origin: *
解决办法
1. 用WordPress的wp_headers钩子强制覆盖CORS头
WordPress的响应头是通过钩子统一处理的,直接写Header()很容易被后面的操作覆盖。你可以在插件里加这段代码,专门针对nostr.json的请求锁死正确的CORS头:
add_filter('wp_headers', function($headers, $wp_query) { $request_uri = $_SERVER['REQUEST_URI']; if (strpos($request_uri, '/.well-known/nostr.json') !== false) { unset($headers['Access-Control-Allow-Origin']); $headers['Access-Control-Allow-Origin'] = '*'; $headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'; $headers['Access-Control-Max-Age'] = '1728000'; } return $headers; }, 999, 2); // 设999优先级,保证最后执行,把其他设置覆盖掉
2. 单独处理OPTIONS预检请求
有些客户端会先发OPTIONS请求做预检,WordPress可能会干扰这个过程,加这段代码直接拦截并返回正确的头:
add_action('init', function() { if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS' && strpos($_SERVER['REQUEST_URI'], '/.well-known/nostr.json') !== false) { header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Methods: POST, GET, OPTIONS"); header("Access-Control-Max-Age: 1728000"); exit; } });
3. 排查第三方干扰
检查下有没有安全插件(比如Wordfence)或者CDN(比如Cloudflare)在自动加CORS头,这些服务经常会根据请求来源动态加域名,导致出现多值的情况。找到对应的配置,把/.well-known/nostr.json路径排除在自动CORS配置外。
4. 用curl精准验证
别信在线工具和wget的差异,用curl模拟真实客户端请求来验证:
curl -H "Origin: https://random-domain.com" -I https://你的域名/.well-known/nostr.json
看返回的头里Access-Control-Allow-Origin是不是只有*。
内容的提问来源于stack exchange,提问作者Pointy Haired Boss

