WordPress双站点API请求401权限异常:Members插件影响排查
解决WordPress Members插件导致跨域Ajax请求REST API 401未授权问题
看起来你遇到的是Members插件在跨域Ajax场景下和REST API Basic Auth的兼容性问题,我帮你梳理下原因和可行的解决办法:
问题核心原因
两个实例唯一差异是Members插件,且Postman能正常请求但Ajax不行,大概率是以下两点:
- Members插件的权限拦截逻辑:该插件会强化WP的权限控制,包括对REST API请求的校验,可能在跨域场景下误拦截了带Basic Auth的请求。
- 浏览器跨域预请求(OPTIONS)的问题:浏览器在发送跨域POST请求前会先发送OPTIONS预请求,这个请求不会携带Authorization头,而Members插件可能没有正确放行OPTIONS请求,导致预请求返回401,进而阻断了实际的POST请求。Postman不受浏览器CORS规则限制,直接发送带Auth头的请求,所以能成功。
具体解决办法
1. 检查并调整Members插件的REST API权限设置
- 登录第二个WP实例后台,进入「插件」→「Members」→「设置」,找到REST API权限相关选项:
- 确认管理员角色拥有
create_posts的REST API权限; - 检查是否有针对跨域请求的额外限制开关,如有则暂时关闭测试。
- 确认管理员角色拥有
- 可以先临时禁用Members插件,测试Ajax请求是否恢复正常,确认问题确实由该插件导致。
2. 修复Ajax代码与服务器端CORS配置
优化Ajax代码
去掉重复的Content-Type设置,避免头信息冲突:
$.ajax({ url: "http://website.test/wp-json/wp/v2/posts", method: "POST", data: JSON.stringify( obj ), crossDomain: true, contentType: "application/json; charset=utf-8", beforeSend: function ( xhr ) { xhr.setRequestHeader( 'Authorization', 'Basic ' + window.btoa("admin:admin") ); }, success: function( data ) { console.log( 'success' ); console.log( data ); }, error: function( error ) { console.log( 'error' ); console.log( error ); } });
服务器端放行OPTIONS预请求
在主题的functions.php中添加以下代码,确保服务器正确处理跨域预请求并放行Authorization头:
add_action( 'rest_api_init', function() { // 替换默认的CORS头处理 remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' ); add_filter( 'rest_pre_serve_request', function( $value ) { // 生产环境建议替换为具体允许的域名,比如 'http://your-frontend-domain.com' header( 'Access-Control-Allow-Origin: *' ); header( 'Access-Control-Allow-Methods: GET, POST, OPTIONS' ); header( 'Access-Control-Allow-Headers: Authorization, Content-Type' ); // 处理OPTIONS预请求,直接返回200 if ( $_SERVER['REQUEST_METHOD'] === 'OPTIONS' ) { status_header(200); exit(); } return $value; }, 15 ); });
3. 改用更安全且兼容的认证方式(长期方案)
Basic Auth存在安全风险,且在部分插件场景下兼容性一般,建议改用WP官方的应用密码(Application Passwords)(WP 5.6及以上版本自带):
- 登录WP后台,进入「用户」→「个人资料」,拉到页面底部找到「应用密码」,创建一个新的应用密码;
- 将Ajax代码中的Authorization头替换为:
xhr.setRequestHeader( 'Authorization', 'Basic ' + window.btoa("admin:你的应用密码") );
Members插件对官方应用密码的兼容性更好,能避免很多权限拦截问题。
内容的提问来源于stack exchange,提问作者user5296504
相关产品推荐
相关产品推荐

