当前位置: 首页 > news >正文

鸿蒙 H5 环境下的 UniApp 跨域与存储兼容性问题排查

在跨端开发中,开发者常常会遇到不同平台、不同运行环境下的兼容性挑战。最近我在用 UniApp 开发一个系统时,就踩到了两个坑:

  • 同域名下不同项目的 storage 数据无法读取
  • 前端 JSONP 跨域在鸿蒙 H5 环境下完全失效

最后只能彻底调整思路,才算找到稳妥的解决方案。本文就来记录整个过程。


一、问题背景

项目中有两个系统:

  • 系统 A(UniApp 开发):业务入口,需要获取 openId 来进行接口调用。
  • 系统 B(同域名下的另一个项目,基于jQuery):在本地存储里已经保存了 openId

最初的思路是:系统 A 直接通过 uni.getStorage 读取系统 B 存储的 openId,然后再通过 JSONP 请求后端接口来规避跨域。

在本地调试和常规浏览器里一切正常,但一旦发布成 H5 并在 鸿蒙系统 下运行,就遇到了两个严重问题。


二、遇到的问题

1. Storage 读取失败

原始代码很简单:

uni.getStorage({key: 'openId',success: function(res) {openId = res.data;}
});

在鸿蒙 H5 环境下,这段逻辑直接失效,拿不到任何数据。虽然两个项目属于同域,但鸿蒙的 WebView 存储机制对不同项目的隔离更严格,导致数据不可见。


2. JSONP 跨域彻底失效

为了请求后端接口,前端使用了 JSONP。iOS和安卓下使用都正常。

// JSONP请求方法
jsonpRequest(url, params, callback) {// 生成唯一的回调函数名const callbackName = 'jsonpCallback' + Date.now() + Math.floor(Math.random() * 10000)// 获取签名参数const mobile = uni.getStorageSync('mobile') || ''const token = uni.getStorageSync('token') || ''if (mobile && token) {const timestamp = Math.round(new Date().getTime() / 1000).toString()const randomStr = this.randomRange(10)const sign = this.hexMD5(timestamp + mobile + token + randomStr)// 添加签名参数params = Object.assign(params, {mobile: mobile,sign: sign,timestamp: timestamp,randomStr: randomStr})}// 添加callback参数params.callback = callbackName// 构建URLconst paramStr = Object.keys(params).map(key => `${key}=${encodeURIComponent(params[key])}`).join('&')const jsonpUrl = `${url}&${paramStr}`// 设置全局回调函数window[callbackName] = (data) => {callback(data)// 清理document.head.removeChild(script)delete window[callbackName]}// 创建script标签const script = document.createElement('script')script.src = jsonpUrlscript.onerror = () => {uni.showToast({title: '网络请求失败',icon: 'none'})// 确保在网络错误时也结束loading状态if (this.loading) {this.loading = falsethis.hasPermission = false}if (this.waitListLoading) {this.waitListLoading = false}document.head.removeChild(script)delete window[callbackName]}document.head.appendChild(script)
},

但是在鸿蒙 WebView 里,JSONP 的回调函数根本不执行,跨域彻底失败。换句话说,原本在浏览器里能跑通的方案,在鸿蒙上完全不可用。


三、原因分析

  1. Storage 问题

    • UniApp 的 uni.getStorage 仅能读取当前应用的本地存储。
    • 不同项目(即使同域名)在鸿蒙 WebView 中被隔离,互不共享存储。
  2. JSONP 跨域问题

    • 鸿蒙系统对 H5 的安全限制更严格。
    • JSONP 本质是 <script> 动态注入,在部分环境下会被拦截或不兼容。

四、解决方案

经过分析,我选择了完全放弃原有方案

  1. 重新获取 openId

    • 不再依赖另一个项目存储的 openId
    • 在当前系统中直接通过 code 流程重新换取 openId,保证应用逻辑的独立性和可靠性。
  2. 使用服务端反向代理代替 JSONP

    • 前端改回标准的 uni.request
    • 在后端配置反向代理,由服务端转发请求到真实接口。
    • 前端看到的始终是同域请求,从根本上解决跨域问题。

    Nginx 配置示例:

     location /api/ {client_max_body_size 300m;rewrite ^/api/(.*)$ /$1 break;proxy_pass https://backend.example.com;proxy_set_header Host fuwu.shiliyiyuan.cn;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_ssl_server_name on;proxy_ssl_verify off;}
    

    前端调用时就非常简洁:

    uni.request({url: '/api/getOpenId',success: (res) => {console.log(res.data);}
    });
    

五、总结与经验

  1. 不要依赖跨项目的 Storage

    • 不同 H5 构建产物就是不同的应用,不能指望共享存储。
    • 在鸿蒙等新环境下,更是完全隔离。
  2. 避免 JSONP

    • JSONP 兼容性差、安全性差,现代环境不推荐使用。
    • 标准请求 + 服务端代理才是更稳妥的解决方案。
  3. 服务端代理是万能解法

    • 对前端透明,兼容所有运行环境。
    • 一旦搭好代理,所有跨域问题迎刃而解。

这次的实践让我更清楚地认识到:

跨平台开发时,兼容性要优先考虑,别抱着“能跑就行”的侥幸心理。与其前端绕路,不如服务端一次性解决。

http://www.dtcms.com/a/418351.html

相关文章:

  • 旧vue3项目集成electron
  • Nature Electronics:卡内基梅隆大学开放用于多模态皮肤反馈的皮肤贴附式触觉接口
  • uniapp div区域长按下载到手机相册为照片
  • Electron 安全实践:渲染进程如何安全使用主进程的三方库能力
  • uniapp集成原生安卓开发的插件
  • 做网站建设需要做哪些工作室Wordpress 转发后查看
  • Kafka面试精讲 Day 24:Spring Kafka开发实战
  • 网站模板 站长之家网站开发需要准备什么
  • bat自动保存论文到制定目录
  • 智能化生产+技术壁垒构建食品容器领军者新天力的上市答卷
  • Qt自定义圆环比例控件
  • 第三方软件测试机构:Appium如何使用Selenium的客户端库?
  • Scikit-learn Python机器学习 - 聚类分析算法 - Agglomerative Clustering(凝聚层次聚类)
  • 便宜的自制 30 MHz - 6 GHz 矢量网络分析仪
  • Meta Ray-Ban Display眼镜将引领AR眼镜的智能化应用落地
  • C++篇 Vector模拟实现(1) 初始化 迭代器遍历 插入尾插尾删 一文详解
  • 学习日报 20250928|React 中实现 “实时检测”:useEffect 依赖项触发机制详解
  • 怎么样可以做自己的网站做网站投注代理犯罪吗
  • 网站空间是服务器吗成都网站设计建设推荐
  • 基于 LangGraph 框架实现智能研究助手示例程序
  • 常用网络命令
  • 实验指导-基于阿里云函数计算的简单邮件发送服务 之数据库访问中间件
  • PPO算法
  • 网站建设公司方维wordpress 上传文件路径
  • gRPC0到1系列之【6】
  • 【Java系列课程·Java学前须知】第3课 JDK,JVM,JRE的区别和优缺
  • JVM栈溢出时如何dump栈信息?
  • 重庆奉节网站建设公司重庆沙坪坝地图全图
  • RK3588芯片与板卡全面解析:旗舰级AIoT与边缘计算的核心
  • 226.翻转二叉树(二叉树算法题)