H5页面及移动端如何保持会话持久化
如何保持移动端会话持久化¶
USER¶
但在很多移动端无法使用Cookie保持会话,此时如何保证用户的登录状态持久化呢?
ASSISTANT¶
这是一个非常经典且切中移动端开发痛点的问题。
首先需要澄清一个常见的误区:移动端 Web(H5 页面在 Safari/Chrome 或 App 的 WebView 中打开)是完全支持并使用 Cookie 的。
你之所以会有“移动端无法使用 Cookie”的印象,通常是因为以下三种真正的移动端场景:
- 原生 App (Native App):iOS (Swift/Obj-C) 和 Android (Java/Kotlin) 的原生网络请求库默认不自动管理 Cookie。
- 跨平台框架:如 React Native、Flutter,它们没有浏览器的
document.cookieAPI。 - 小程序:微信/支付宝小程序运行在封闭的沙箱环境中,没有传统的 Cookie 机制。
在这些**非浏览器环境**中,为了保证用户登录状态的持久化(即“杀掉 App 进程或重启手机后依然保持登录”),业界有一套成熟且比 Cookie **更安全、更可控**的替代方案。
核心思路是:安全本地存储 + 双 Token 机制 + 移动端特有风控。
1. 核心方案:使用系统级“安全存储”替代 Cookie¶
在移动端,我们绝不使用普通的、明文的本地存储(如 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 机制来平衡“安全性”与“持久化体验”:
- Access Token (短效,如 2 小时):
- 存储:App 运行期间存在**内存**中(变量里)。
- 用途:每次发起 API 请求时,由网络拦截器(如 OkHttp Interceptor, Dio Interceptor)自动添加到 Header (
Authorization: Bearer <token>) 中。 - 持久化:不持久化。App 杀掉进程后就消失。
- Refresh Token (长效,如 30 天):
- 存储:存在上述的 Keychain / Keystore 中。
- 用途:当 Access Token 过期,后端返回
401 Unauthorized时,前端的网络拦截器会**静默拦截**这个错误,自动从安全存储中取出 Refresh Token,向后端请求一个新的 Access Token。 - 体验:整个刷新过程在毫秒级完成,用户完全无感知,实现了“持久化登录”。只有当 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 机制,换用了一套更适合原生环境、安全性更高的组合拳**:
- 存储介质升级:用系统级加密存储 (Keychain/Keystore) 替代 Cookie。
- 架构升级:用内存 Access Token + 持久化 Refresh Token 实现无感刷新。
- 通信桥接:用 JSBridge 解决原生与 H5 的会话共享。
- 风控兜底:用设备指纹绑定,让偷来的 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> 中几乎必有这行代码:
<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 页面需要处理与桌面端完全不同的交互方式:
// 桌面端:鼠标事件
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 / 桌面 |
注意: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 页面最适合以下场景:
- 营销活动页:双十一会场、抽奖转盘、年度账单 — 需要快速上线、频繁更新、通过链接/二维码分享
- 电商商品详情页:淘宝/京东的商品页大量使用 H5,便于动态更新内容和 A/B 测试
- 内容资讯流:新闻、文章、博客 — 内容驱动,对性能要求不高
- 表单与问卷:报名表、调查问卷 — 开发快,分发方便
- App 内的非核心页面:设置页、帮助中心、协议条款 — 用 H5 开发可以热更新,不用发版
- 跨平台 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% 的高危漏洞,主要集中在后端和接口层面:
- 业务逻辑漏洞:如支付逻辑篡改、密码重置流程缺陷、验证码绕过等。
- 越权访问:水平越权(查看/修改他人数据)、垂直越权(普通用户执行管理员操作)。
- 注入类漏洞:SQL 注入、命令注入、NoSQL 注入、LDAP 注入等(只要后端没做好过滤)。
- API 安全:未授权访问、敏感信息泄露(接口返回了不该返回的手机号、身份证等)、CORS 配置错误。
- 参数篡改与重放:修改请求参数、重放关键请求。
三、 这个方案的致命盲区(H5 测不出什么?)¶
这是你必须向项目方或客户明确的风险。原生 APP 本身也是一个攻击面,H5 无法覆盖原生代码特有的安全问题:
- 本地数据存储安全:APP 可能会将敏感数据(如 Token、密码、聊天记录)明文存储在
SharedPreferences、SQLite或Keychain/Keystore配置不当的地方。H5 页面无法测试这些本地文件的读写安全。 - 客户端硬编码与逆向风险:APP 原生代码中可能硬编码了 AES/RSA 密钥、第三方 SDK 的 Secret Key。H5 是混淆后的 JS,攻击面不同。
- 原生组件漏洞:
- Android 的
Intent劫持、组件暴露(Exported 组件)、WebView 漏洞(如addJavascriptInterface未禁用)。 - iOS 的 URL Scheme 劫持、Keychain 访问控制、剪贴板读取等。
- 特定的设备指纹与风控:APP 可能会调用原生的设备指纹 SDK(如获取 IMEI、MAC、传感器数据),H5 只能获取浏览器环境的信息。如果后端对 APP 和 H5 的风控策略不同,H5 测试无法发现 APP 特有的风控绕过问题。
- 本地加密/签名逻辑:很多 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 成本太高”而拒绝配合。此时你可以考虑以下替代方案:
- 寻找其他端:除了 APP 和 H5,有没有 Web 端(PC 网页) 或 微信小程序?如果有,且它们调用的是同一套 API,直接去测 Web 端或小程序(小程序抓包相对容易)。
- 技术突破(硬刚抓包):
- 如果是 Android,使用 Frida 结合
JustTrustMe或ssl_unpinning脚本,Hook 掉证书绑定(Certificate Pinning)。 - 如果是 iOS,越狱后使用 Frida 或 Objection 绕过 SSL Pinning。
- 如果是有强壳(如 360、腾讯御安全),先使用脱壳工具(如 Frida-DEXDump、BlackDex)脱壳,再进行 Hook。
- 直接测试 API:如果公司有 Swagger、YApi 或 Postman 的 API 文档,直接导入 Postman,使用 APP 登录获取的 Token,在 Postman 里直接对 API 进行模糊测试(Fuzzing)和逻辑测试,完全绕过客户端。
总结¶
让开发做一套 H5 来替代 APP 进行安全测试,是一个**高性价比、能快速覆盖后端核心业务逻辑漏洞**的聪明策略。
但作为安全测试人员,你必须在报告中明确声明:“本次测试基于 H5 替代方案,覆盖了后端 API 及业务逻辑安全,但未包含原生客户端的本地存储、组件安全及逆向风险。” 这样既完成了核心测试目标,又规避了自身的责任风险。