鸿蒙Cordova开发踩坑记录:跨域请求的“隐形墙“

摘要 :在开发调试阶段,我们经常遇到一个诡异现象:在浏览器里运行正常的 AJAX 请求,一放到鸿蒙真机上就报错 Network ErrorCORS error。这通常是因为混合应用运行在 file://resource:// 协议下,被浏览器的同源策略(Same-Origin Policy)无情拦截。本文讲解如何配置 ArkWeb 的跨域白名单。

🚧 1. 隐形的高墙

当前端页面位于 index.html (本地文件) 时,它的 Origin 是 file://null

当它尝试请求后端接口 https://api.game-server.com/score 时,这就构成了一个跨域请求

现代 WebView 的安全策略越来越严:

  1. 禁止 file:// 访问 http/https(Mixed Content)。
  2. 禁止 file:// 发送 AJAX 到任何域(除非服务器显式允许 Access-Control-Allow-Origin: *)。
  3. Preflight (OPTIONS) 请求失败。

🛠️ 2. 爆破方案

我们不需要后端配合改 Header(因为有时候调的是第三方 API),我们可以从客户端侧**"解除封印"**。

2.1 方案一:Web组件配置 (ArkTS)

ArkWeb 提供了若干个开关,用于放宽安全限制。

typescript 复制代码
Web({ src: this.url, controller: this.controller })
  .domStorageAccess(true)
  .fileAccess(true)
  .imageAccess(true)
  // 关键:允许混合内容(https 页面加载 http 资源)
  .mixedMode(MixedMode.All) 
  // 关键:允许 file 协议下的跨域访问
  .fileAccess(true) 
  .javaScriptAccess(true)

注意:仅靠这些配置,在某些高版本 Android/鸿蒙内核上,CORS 依然会被拦截。

2.2 方案二:代理转发 (Interceptor) ✅

这是最稳妥的方案。既然 Webview 限制跨域,那我们就让 Native 代码去发请求。Native 的 HTTP 请求(http.createHttp())是不受同源策略限制的。

原理

Web -> 拦截特定 URL -> Native HTTP -> Server -> Native -> Web

我们复用第 8 篇中的 onInterceptRequest 机制:

typescript 复制代码
// GamePlugin.ets

// 拦截 /api/ 前缀的请求
if (url.includes('/api/')) {
    // 使用鸿蒙原生网络库发送请求
    let httpRequest = http.createHttp();
    let response = await httpRequest.request(realApiUrl, {
        method: 'POST',
        header: { 'Content-Type': 'application/json' },
        extraData: requestBody
    });
    
    // 构造 Web 响应,并手动添加 CORS 头
    let webResponse = new WebResourceResponse();
    webResponse.setResponseHeader([
        { headerKey: "Access-Control-Allow-Origin", headerValue: "*" } // 强行允许
    ]);
    webResponse.setResponseData(response.result);
    return webResponse;
}

2.3 方案三:Cordova HTTP 插件

如果你不想自己写拦截器,可以直接使用社区成熟的插件 cordova-plugin-advanced-http

它会在 JS 层替换标准的 fetchXMLHttpRequest,底层通过 Native 代码发送请求。

优点

  • 自动处理 SSL Pinning。
  • 无视 CORS。
  • 支持 Cookie 管理。

Web 端代码

javascript 复制代码
cordova.plugin.http.post('https://api.example.com/data', {
    id: 123
}, {
    Authorization: 'Bearer token'
}, function(response) {
    console.log(response.status);
}, function(response) {
    console.error(response.error);
});

🕸️ 3. UserAgent 伪装

有时候请求被拒不是因为跨域,而是因为服务器把来自 WebView 的请求当成了爬虫或非法客户端。

我们可以修改 UA 来伪装身份。

typescript 复制代码
Web({ ... })
  .userAgent("Mozilla/5.0 (Phone; HarmonyOS; GameApp/1.0) AppleWebKit/537.36")

这对于请求一些对 UA 敏感的 CDN 资源(如防盗链图片)非常有用。

📚 4. 总结

面对跨域墙:

  1. 初级 :配置 mixedModefileAccess(仅对部分旧内核有效)。
  2. 中级:后端开启 CORS(需要控制权)。
  3. 高级Native 代理转发。这是终极解决方案,它不仅解决了 CORS,还能解决 SSL 证书校验、自定义 DNS 解析等高级网络需求。

在混合开发中,把网络层下沉到 Native,虽然麻烦一点,但能避开 Web 安全策略的无尽骚扰。

相关推荐
tyqtyq2215 小时前
药品说明书解读 —— AI 安全用药助手,鸿蒙原生应用深度解析
人工智能·学习·华为·生活·harmonyos
风华圆舞16 小时前
鸿蒙HarmonyOS滚字组件实战 —— 逐字 Slot Roll,从浏览器到原生 ArkUI
华为·harmonyos·arkui·slottext·measureutils·共享时间轴·滚字
不羁的木木16 小时前
HarmonyOS APP实战-画图APP - 第8篇:图像效果应用(亮度/模糊/灰度)
华为·harmonyos
●VON17 小时前
HarmonyKit | 鸿蒙开发展望:HarmonyKit 未来路线图与社区共建
华为·单元测试·harmonyos·鸿蒙
HarmonyOS_SDK17 小时前
借助游戏预启动提前加载游戏,读条快人一步
harmonyos
不羁的木木17 小时前
HarmonyOS APP实战-画图APP - 第3篇:矩形与圆形绘制
华为·harmonyos
绝世番茄18 小时前
Column 与 if/else 条件渲染:动态子组件的布局行为
华为·harmonyos·鸿蒙
花开彼岸天~19 小时前
鸿蒙实战:AppStorage 全局状态管理
华为·harmonyos·鸿蒙系统
爱吃大芒果19 小时前
鸿蒙 7 新特性科普:什么是系统 Agent 智能体?
华为·harmonyos·智能体
listening77719 小时前
HarmonyOS 6.1 元服务实战:把电商卡片装进系统“负一屏”
华为·harmonyos