跳转至

H5页面及移动端如何保持会话持久化

如何保持移动端会话持久化

USER

但在很多移动端无法使用Cookie保持会话,此时如何保证用户的登录状态持久化呢?

ASSISTANT

这是一个非常经典且切中移动端开发痛点的问题。

首先需要澄清一个常见的误区:移动端 Web(H5 页面在 Safari/Chrome 或 App 的 WebView 中打开)是完全支持并使用 Cookie 的。

你之所以会有“移动端无法使用 Cookie”的印象,通常是因为以下三种真正的移动端场景:

  1. 原生 App (Native App):iOS (Swift/Obj-C) 和 Android (Java/Kotlin) 的原生网络请求库默认不自动管理 Cookie。
  2. 跨平台框架:如 React Native、Flutter,它们没有浏览器的 document.cookie API。
  3. 小程序:微信/支付宝小程序运行在封闭的沙箱环境中,没有传统的 Cookie 机制。

在这些**非浏览器环境**中,为了保证用户登录状态的持久化(即“杀掉 App 进程或重启手机后依然保持登录”),业界有一套成熟且比 Cookie **更安全、更可控**的替代方案。

核心思路是:安全本地存储 + 双 Token 机制 + 移动端特有风控。


在移动端,我们绝不使用普通的、明文的本地存储(如 Android 的普通 SharedPreferences 或 iOS 的普通 UserDefaults,因为它们在手机 Root/越狱后极易被读取)。

取而代之的是调用操作系统的**硬件级加密存储**:

  • iOS (原生):使用 Keychain (钥匙串)。这是 iOS 系统提供的加密存储区域,即使 App 被卸载,只要用户不抹掉手机,Keychain 中的数据通常依然保留(可实现真正的“卸载重装免登录”),且极难被破解。
  • Android (原生):使用 EncryptedSharedPreferences (基于 Android Keystore 系统)。它将数据加密后再存储,密钥由硬件级别的 TEE (可信执行环境) 保护。
  • React Native:使用 react-native-keychain 或 expo-secure-store(底层自动映射到 iOS Keychain 和 Android Keystore)。
  • Flutter:使用 flutter_secure_storage 插件(同样底层调用原生安全存储)。

做法:将长效的 Refresh Token 存入上述安全存储中,实现持久化。


2. 架构配合:双 Token 机制 (Access Token + Refresh Token)

移动端几乎 100% 采用双 Token 机制来平衡“安全性”与“持久化体验”:

  1. Access Token (短效,如 2 小时):
  2. 存储:App 运行期间存在**内存**中(变量里)。
  3. 用途:每次发起 API 请求时,由网络拦截器(如 OkHttp Interceptor, Dio Interceptor)自动添加到 Header (Authorization: Bearer <token>) 中。
  4. 持久化:不持久化。App 杀掉进程后就消失。
  5. Refresh Token (长效,如 30 天):
  6. 存储:存在上述的 Keychain / Keystore 中。
  7. 用途:当 Access Token 过期,后端返回 401 Unauthorized 时,前端的网络拦截器会**静默拦截**这个错误,自动从安全存储中取出 Refresh Token,向后端请求一个新的 Access Token。
  8. 体验:整个刷新过程在毫秒级完成,用户完全无感知,实现了“持久化登录”。只有当 Refresh Token 也过期,或被后端主动吊销时,才会跳转到登录页。

3. 特殊场景的解决方案

A. 微信小程序环境

小程序没有 Keychain,官方提供的 wx.setStorageSync 本质上是明文的本地文件存储。

  • 如何应对:
  • 微信沙箱环境相对封闭,普通用户无法直接访问 App 的文件目录,风险低于开放的 Android 文件系统。
  • 小程序通常结合 微信登录 (wx.login)。持久化的其实不是 JWT,而是一个 code 换取的 session_key 或自定义的短效 Token。
  • 严重依赖后端的**设备指纹风控**(见下文)。
B. Hybrid App (原生 App 内嵌 H5 页面)

这是移动端最头疼的场景:用户在原生 App 登录了,打开内嵌的 H5 页面,H5 怎么知道用户登录了?(因为 H5 拿不到原生的 Keychain)。

  • 解决方案:JSBridge 通信
  • H5 页面加载时,通过 JSBridge 向原生 App 发送消息:"请给我当前的 Token"。
  • 原生 App 从 Keychain/Keystore 中安全地取出 Token,通过 JSBridge 回调返回给 H5。
  • H5 拿到 Token 后,将其注入到自己的网络请求库(如 Axios)的 Header 中,或者临时写入当前 WebView 的 Cookie 中,从而完成 H5 侧的鉴权。

4. 移动端独有的终极兜底:设备指纹与风控

在 Web 端,我们害怕 Token 被偷,是因为攻击者可以把 Token 复制到另一台电脑上使用。 但在移动端,后端拥有更强大的**设备级风控能力**,这使得即使 Token 泄露,风险也大幅降低:

  • 设备绑定:后端在首次登录时,会记录该 Token 对应的 Device ID (iOS 的 IDFV/Android 的 OAID 或自生成的 UUID)。
  • 异常拦截:如果后端发现一个 Token 突然从一个完全陌生的设备 ID 或异常的 IP 地理位置发起请求,即使 Token 是合法的,后端也会**拒绝服务**,并要求用户进行二次验证(如短信验证码、人脸识别)。
  • 远程吊销:用户在 App 设置中点击“退出所有设备登录”,后端只需将该 Refresh Token 加入黑名单,攻击者手中的 Token 瞬间作废。

总结

移动端并不是“无法保持会话”,而是**抛弃了浏览器时代遗留的 Cookie 机制,换用了一套更适合原生环境、安全性更高的组合拳**:

  1. 存储介质升级:用系统级加密存储 (Keychain/Keystore) 替代 Cookie。
  2. 架构升级:用内存 Access Token + 持久化 Refresh Token 实现无感刷新。
  3. 通信桥接:用 JSBridge 解决原生与 H5 的会话共享。
  4. 风控兜底:用设备指纹绑定,让偷来的 Token 在异地无法使用。

这套体系不仅解决了持久化问题,其整体安全性实际上**高于**传统的纯 Cookie 或纯 LocalStorage 方案。

H5页面是什么

一、什么是"H5"?

"H5"是中国互联网行业的一个特有叫法,它并不是一个严格的技术标准,而是 HTML5 的简称。在实际语境中,"H5页面"泛指**在移动端(手机/平板)上运行的 Web 网页**。

在国外,开发者通常直接说 "Mobile Web" 或 "Responsive Web",不会用"H5"这个词。

所以,H5 页面本质上就是**用 Web 技术(HTML + CSS + JavaScript)开发的、专门为移动端屏幕和交互优化过的网页**。


二、核心技术栈

H5 页面的底层技术与桌面端 Web 完全一致,但在适配和交互上有大量移动端特有的实践。

1. 基础三件套

技术 作用 移动端特殊关注点
HTML5 页面结构与语义 新增 <video>, <audio>, <canvas>, 地理位置 API 等移动端高频使用的标签和 API
CSS3 样式与布局 弹性布局 (Flexbox)、Grid、动画 (Animation/Transition)、媒体查询 (Media Query)
JavaScript (ES6+) 交互逻辑 触摸事件 (Touch Events)、设备传感器 API、Service Worker 等

2. 移动端适配(最核心的差异)

桌面端网页通常假设屏幕宽度 ≥ 1024px,而移动端屏幕宽度从 320px 到 430px 不等,且存在各种刘海屏、折叠屏。因此 H5 开发有一套专门的适配体系:

a) Viewport 设置

每个 H5 页面的 <head> 中几乎必有这行代码:

HTML
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

它告诉浏览器:不要用桌面端的缩放逻辑来渲染页面,按设备实际宽度来显示。

b) 布局适配方案
方案 原理 适用场景
rem 动态设置根元素 font-size,所有尺寸用 rem 单位 传统方案,配合 lib-flexible 库使用
vw/vh 直接使用视口宽度/高度的百分比(1vw = 1% 屏幕宽度) 现代主流方案,简洁直观
postcss-px-to-viewport 开发时写 px,构建时自动转换为 vw 工程化方案,开发体验最好
媒体查询 @media (max-width: 768px) { ... } 响应式网站(同时兼容桌面和移动端)
c) 高清屏适配(1px 问题)

现代手机屏幕的 DPR (Device Pixel Ratio) 通常是 2 或 3,即 1 个 CSS 像素对应 2~3 个物理像素。这导致 CSS 写的 1px 边框在手机上看起来偏粗。常见解决方案:

  • 使用 transform: scale(0.5) 缩放伪元素
  • 使用 border-image 或 SVG
  • 使用 0.5px(部分现代浏览器已支持)

3. 移动端特有的交互

H5 页面需要处理与桌面端完全不同的交互方式:

JavaScript
// 桌面端:鼠标事件
element.addEventListener('click', handler);
element.addEventListener('mouseover', handler);

// 移动端:触摸事件
element.addEventListener('touchstart', handler);   // 手指按下
element.addEventListener('touchmove', handler);     // 手指滑动
element.addEventListener('touchend', handler);      // 手指抬起

// 移动端常见的"300ms 点击延迟"问题
// 解决方案:使用 CSS `touch-action: manipulation` 或引入 FastClick 库

其他移动端特有交互:

  • 手势识别:滑动 (Swipe)、捏合缩放 (Pinch)、长按 (Long Press) — 通常使用 Hammer.js 等库
  • 下拉刷新 / 上拉加载更多:需要监听 touchmove 和 scroll 事件
  • 软键盘弹出:需要处理输入框被键盘遮挡的问题

三、运行环境(H5 页面在哪里跑?)

这是理解 H5 技术的关键。同一个 H5 页面,可以在多种完全不同的容器中运行:

1. 系统浏览器

  • iOS Safari、Android Chrome / 系统自带浏览器
  • 特点:功能最完整,支持最新的 Web API,用户可自由访问

2. App 内嵌 WebView

  • 原生 App 中通过 WebView 组件加载 H5 页面
  • iOS 使用 WKWebView,Android 使用 WebView (Chromium 内核)
  • 特点:可以通过 JSBridge 与原生能力通信(调用摄像头、支付、获取 Token 等),但 WebView 版本可能较旧,存在兼容性坑

3. 超级 App 内置浏览器

  • 微信内置浏览器(基于 X5 内核 / WKWebView)
  • 支付宝内置浏览器
  • 抖音内置浏览器
  • 特点:提供了丰富的 JS-SDK(如微信的 wx.config),可调用分享、支付、扫码等原生能力,但有诸多限制(如域名白名单、部分 API 被禁用)

4. PWA (Progressive Web App)

  • 通过 Service Worker 实现离线缓存、推送通知
  • 可"安装"到手机桌面,体验接近原生 App
  • 特点:在 Android Chrome 上支持较好,iOS Safari 支持有限

四、主流开发框架与 UI 库

现代 H5 开发几乎不会手写原生 HTML/CSS/JS,而是使用成熟的框架生态:

1. 前端框架(逻辑层)

框架 特点 在 H5 中的地位
Vue 3 上手简单,中文生态强大 国内 H5 开发的**绝对主流**
React 灵活强大,社区庞大 国际化项目和大厂偏爱
Svelte 编译时框架,体积极小 小众但增长中

2. 移动端 UI 组件库

库名 配套框架 特点
Vant Vue 有赞出品,国内最流行的移动端 Vue 组件库,电商场景丰富
NutUI Vue / React 京东出品,京东风格
Ant Design Mobile React 蚂蚁出品,设计规范成熟
Varlet Vue 3 Material Design 风格

3. 跨端框架(一套代码 → 多端运行)

这是移动端 H5 开发中极其重要的一类工具,目标是 "写一次代码,同时生成 H5、微信小程序、App":

框架 语法 输出目标 出品方
uni-app Vue 语法 H5 + 微信/支付宝/抖音小程序 + App (iOS/Android) DCloud
Taro React / Vue 语法 H5 + 各平台小程序 + React Native App 京东
React Native React 语法 原生 iOS / Android App(非 H5,但技术栈相关) Meta
Flutter Dart 语言 原生 iOS / Android / Web / 桌面 Google

注意:uni-app 和 Taro 生成的 H5 页面本质上还是标准的 HTML/CSS/JS,只是开发时用了一套统一的 API 和组件规范。


五、H5 可调用的移动端特有 Web API

现代移动浏览器和 WebView 提供了大量硬件级 API,让 H5 页面的能力远超桌面端:

API 能力 典型场景
Geolocation API 获取 GPS 定位 外卖、地图、附近的人
Camera / MediaDevices 调用摄像头拍照/录像 扫码、人脸识别、头像上传
DeviceOrientation 陀螺仪 / 加速度计 摇一摇、AR 互动、体感游戏
Vibration API 手机震动 游戏反馈、消息提醒
Web Bluetooth / NFC 蓝牙 / NFC 通信 连接智能硬件、刷公交卡
Web Audio API 高级音频处理 语音消息、音乐播放器
File API + FileReader 读取本地文件 图片选择与预览
Wake Lock API 阻止屏幕休眠 导航、视频播放

六、H5 vs 原生 App 对比

维度 H5 页面 原生 App
开发成本 低(一套代码跨平台) 高(iOS + Android 两套代码)
发布更新 即时生效,无需审核 需要提交应用商店审核(数小时~数天)
性能 中等(受限于 WebView 渲染) 高(直接调用系统 API,60fps 流畅)
用户体验 接近原生,但复杂动画/手势有差距 最佳
离线能力 弱(依赖网络,PWA 可部分弥补) 强(可完全离线运行)
硬件调用 有限(依赖浏览器/WebView 支持) 完全访问所有硬件
分发方式 URL 链接,扫码即开 应用商店下载安装

七、典型应用场景

H5 页面最适合以下场景:

  1. 营销活动页:双十一会场、抽奖转盘、年度账单 — 需要快速上线、频繁更新、通过链接/二维码分享
  2. 电商商品详情页:淘宝/京东的商品页大量使用 H5,便于动态更新内容和 A/B 测试
  3. 内容资讯流:新闻、文章、博客 — 内容驱动,对性能要求不高
  4. 表单与问卷:报名表、调查问卷 — 开发快,分发方便
  5. App 内的非核心页面:设置页、帮助中心、协议条款 — 用 H5 开发可以热更新,不用发版
  6. 跨平台 MVP(最小可行产品):创业初期用 H5 快速验证想法,后期再考虑原生

总结

移动端 H5 页面 = 标准 Web 技术 (HTML5 + CSS3 + JS) + 移动端适配方案 + 移动端特有 API + 特定的运行容器 (浏览器/WebView/超级App)

它不是一项独立的技术,而是 Web 前端技术在移动场景下的延伸和特化。在中国互联网生态中,由于微信等超级 App 的存在,H5 页面的重要性远超国外,是前端工程师必须掌握的核心技能之一。

H5在安全测试中的运用

USER

如果要对一个APP进行安全测试,但无法对其抓包,可否让开发团队配合做一套对应的H5页面做替代进行测试

ASSISTANT

这是一个非常专业且切中移动端安全测试痛点的问题。

直接回答你的问题:完全可行,并且这是业界在遇到“强壳”、“证书绑定(Certificate Pinning)”等无法抓包情况时,非常推荐且常用的一种变通策略(Workaround)。

但是,H5 页面不能完全替代原生 APP 的安全测试。你需要清楚地知道这个方案“能测出什么”以及“会漏掉什么”。

以下是详细的分析和实操建议:

一、 为什么这个方案有效?(核心原理)

现代 APP 的架构绝大多数是“薄客户端,厚服务端”。APP 原生代码(iOS/Android)主要负责 UI 渲染和本地交互,核心的业务逻辑、数据处理和鉴权都在后端 API 上。

通常情况下,APP 和 H5 页面调用的是同一套后端 API(或者高度相似的接口)。 当你无法对 APP 抓包时,你实际上是无法看到“客户端与后端通信的明文数据”。而让开发提供 H5 页面,H5 运行在浏览器或普通 WebView 中,没有严格的证书绑定,你可以轻松配置代理(如 Burp Suite、Charles)进行抓包。

本质上,你是通过测试 H5 的接口,来间接测试了后端 API 的安全性。

二、 这个方案能覆盖哪些安全测试?(优势)

通过 H5 抓包,你可以覆盖移动端安全测试中 70%~80% 的高危漏洞,主要集中在后端和接口层面:

  1. 业务逻辑漏洞:如支付逻辑篡改、密码重置流程缺陷、验证码绕过等。
  2. 越权访问:水平越权(查看/修改他人数据)、垂直越权(普通用户执行管理员操作)。
  3. 注入类漏洞:SQL 注入、命令注入、NoSQL 注入、LDAP 注入等(只要后端没做好过滤)。
  4. API 安全:未授权访问、敏感信息泄露(接口返回了不该返回的手机号、身份证等)、CORS 配置错误。
  5. 参数篡改与重放:修改请求参数、重放关键请求。

三、 这个方案的致命盲区(H5 测不出什么?)

这是你必须向项目方或客户明确的风险。原生 APP 本身也是一个攻击面,H5 无法覆盖原生代码特有的安全问题:

  1. 本地数据存储安全:APP 可能会将敏感数据(如 Token、密码、聊天记录)明文存储在 SharedPreferences、SQLite 或 Keychain/Keystore 配置不当的地方。H5 页面无法测试这些本地文件的读写安全。
  2. 客户端硬编码与逆向风险:APP 原生代码中可能硬编码了 AES/RSA 密钥、第三方 SDK 的 Secret Key。H5 是混淆后的 JS,攻击面不同。
  3. 原生组件漏洞:
  4. Android 的 Intent 劫持、组件暴露(Exported 组件)、WebView 漏洞(如 addJavascriptInterface 未禁用)。
  5. iOS 的 URL Scheme 劫持、Keychain 访问控制、剪贴板读取等。
  6. 特定的设备指纹与风控:APP 可能会调用原生的设备指纹 SDK(如获取 IMEI、MAC、传感器数据),H5 只能获取浏览器环境的信息。如果后端对 APP 和 H5 的风控策略不同,H5 测试无法发现 APP 特有的风控绕过问题。
  7. 本地加密/签名逻辑:很多 APP 会在本地对请求参数进行签名(Sign)或加密。虽然 H5 可能也有类似逻辑,但 APP 的签名算法可能结合了原生底层 API,H5 的 JS 实现可能与之不同。

四、 实操建议:如何让这个方案发挥最大价值?

如果你决定采用这个方案,请务必与开发团队确认以下细节,否则测试可能无效:

1. 确认“接口一致性”
  • 灵魂拷问:H5 调用的后端接口,和 APP 调用的接口,真的是同一个吗?
  • 有些公司为了区分端,会写两套接口(如 /api/v1/app/login 和 /api/v1/h5/login)。如果是这样,H5 的测试结果不能直接推导到 APP 上。
  • 对策:要求开发提供 H5 时,明确指出 H5 调用的是与 APP 完全相同的底层 API。
2. 确认“鉴权机制一致性”
  • 如前文所述,APP 通常用 Authorization: Bearer <token>,而 H5 可能用 Cookie。
  • 对策:确保后端对这两种鉴权方式的安全校验级别是一致的。在测试 H5 时,不仅要测 H5 的 Cookie 鉴权,最好能手动把 APP 的 Token 塞进 H5 的请求头里测一下,看后端是否认。
3. 确认“运行容器”
  • H5 是跑在系统浏览器里,还是跑在微信/支付宝的 WebView 里,或者是 App 自己的 WebView 里?
  • 如果是跑在 App 自己的 WebView 里,依然要确认该 WebView 是否禁用了不安全的设置(如是否允许了 JS 注入)。
4. 补充“静态分析”
  • 既然动态抓包用 H5 替代了,那么对于 APP 原生代码的测试,必须补充**静态分析**。
  • 使用工具(如 MobSF、Jadx、Hopper)对 APP 的 APK/IPA 进行反编译,检查代码中的硬编码、不安全的本地存储、组件暴露等问题,以弥补 H5 动态测试的盲区。

五、 如果开发团队不配合怎么办?

有时候开发团队会觉得“写一套 H5 成本太高”而拒绝配合。此时你可以考虑以下替代方案:

  1. 寻找其他端:除了 APP 和 H5,有没有 Web 端(PC 网页) 或 微信小程序?如果有,且它们调用的是同一套 API,直接去测 Web 端或小程序(小程序抓包相对容易)。
  2. 技术突破(硬刚抓包):
  3. 如果是 Android,使用 Frida 结合 JustTrustMe 或 ssl_unpinning 脚本,Hook 掉证书绑定(Certificate Pinning)。
  4. 如果是 iOS,越狱后使用 Frida 或 Objection 绕过 SSL Pinning。
  5. 如果是有强壳(如 360、腾讯御安全),先使用脱壳工具(如 Frida-DEXDump、BlackDex)脱壳,再进行 Hook。
  6. 直接测试 API:如果公司有 Swagger、YApi 或 Postman 的 API 文档,直接导入 Postman,使用 APP 登录获取的 Token,在 Postman 里直接对 API 进行模糊测试(Fuzzing)和逻辑测试,完全绕过客户端。

总结

让开发做一套 H5 来替代 APP 进行安全测试,是一个**高性价比、能快速覆盖后端核心业务逻辑漏洞**的聪明策略。

但作为安全测试人员,你必须在报告中明确声明:“本次测试基于 H5 替代方案,覆盖了后端 API 及业务逻辑安全,但未包含原生客户端的本地存储、组件安全及逆向风险。” 这样既完成了核心测试目标,又规避了自身的责任风险。