You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ionic本地开发遇CORS错误,已配置请求头仍报错

本地Ionic应用XHR请求CORS错误排查:已配置.htaccess仍报错的原因

我正在本地开发一款使用XHR请求的Ionic应用,但出现了CORS错误。

错误信息

从源'http://localhost:8100'访问'http://id:pwd@mydomain.com/app/proDB.jsonp'的XMLHttpRequest被CORS策略阻止:请求的资源上不存在'Access-Control-Allow-Origin'头。

服务器.htaccess配置(路径:/home/gwwdpcf/www/app/.htaccess)

AuthType Basic 
AuthName "L pit blod"
AuthUserFile /home/gwwdpcf/www/app/.htpasswd
require valid-user

#   Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"
#   Header add Access-Control-Allow-Origin "*"

# Enable cross domain access control
Header add Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
Header always set Access-Control-Allow-Headers: Authorization
Header set Access-Control-Allow-Credentials true


# Force to request 200 for options
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]

客户端代码片段

const url = dbUrl() {  
    return decodeURIComponent(decodeURIComponent("http://example.org/app/proDB.jsonp"))    
  }

  const username = 'id';
  const password = 'pwd';
  const credentials = username + ':' + password;
  const base64Credentials = btoa(credentials);
  var request = new XMLHttpRequest();
  request.open('GET', url, true);  
  request.setRequestHeader('Authorization', 'Basic ' + base64Credentials);
  request.setRequestHeader('Content-Type', 'application/xml');  // Assuming you're expecting XML data

  if (url === "proDB.jsonp") {
    console.log("--Asking local proDB.json...");
  } else {
    console.log("--Sending XMLHttpRequest...");
  }

  request.timeout = XHRtimeout;
  request.ontimeout = function () {    
    reject({
      status: this.status,
      statusText: request.statusText,
    });
  };
  request.onload = async function () {
    if (
      request.readyState === 4 &&
      ((request.status >= 200 && request.status <= 299) ||
        request.status === 304 ||
        request.status === 0)
    ) {   
 ...

补充截图

Chrome调试工具CORS相关截图


问题原因与修复方案

核心问题分析

  1. Basic Auth拦截预检请求
    服务器启用了Basic Auth,浏览器发送的OPTIONS预检请求不会携带Authorization头,直接被服务器拦截,导致CORS头无法返回给浏览器,这就是报错提示头不存在的根本原因。

  2. CORS配置互斥
    Access-Control-Allow-Credentials: true和Access-Control-Allow-Origin: "*"不能同时使用——当允许携带凭证(如Authorization头)时,Origin必须指定具体域名,不能用通配符。

  3. OPTIONS请求重定向错误
    现有Rewrite规则把OPTIONS请求重定向到根路径/,但根路径的配置和/app/不一致,导致预检请求响应依然缺少CORS头,重定向本身也会触发浏览器的CORS校验失败。

修复步骤

1. 让OPTIONS请求跳过Basic Auth

在Basic Auth配置前添加规则,允许OPTIONS请求无需认证:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L,E=HTTP_ORIGIN:%{HTTP:ORIGIN}]

AuthType Basic 
AuthName "L pit blod"
AuthUserFile /home/gwwdpcf/www/app/.htpasswd
require valid-user

2. 修正CORS头配置

替换原CORS配置,指定具体Origin并兼容凭证携带:

# Enable cross domain access control
Header always set Access-Control-Allow-Origin "http://localhost:8100"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "Authorization, Content-Type"
Header always set Access-Control-Allow-Credentials true

3. 移除错误的OPTIONS重定向规则

删掉RewriteRule .* / [R=200,L],改用上面的Rewrite规则处理OPTIONS请求。

4. 客户端验证

保持当前用Authorization头传递凭证的逻辑,避免在URL中直接携带账号密码;确保Content-Type已包含在服务器允许的Headers列表中(已在步骤2配置)。

内容的提问来源于stack exchange,提问作者Louis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:04:53