如何通过 addJavascriptInterface 实现 JS 调用 Android 方法?存在哪些安全漏洞?
解读
国内面试中,这道题既考察“JSBridge”基础实现,也暗含对混合开发安全红线的认知。面试官通常先让你口述最小可运行流程,再追问“低版本系统漏洞”“意图劫持”“代码注入”等场景,最终落到“如何闭环加固”。回答时要体现:
- 最小实现 → 2. 漏洞原理 → 3. 国内合规要求(工信部 164 号文、个人信息保护合规)→ 4. 线上加固方案。
切忌只背“@JavascriptInterface”关键字,而要展示“攻击—检测—加固—回滚”全链路视角。
知识点
- WebView.addJavascriptInterface(Object object, String jsName) 机制
- Java 反射与注解 @JavascriptInterface(API 17+ 强制)
- 漏洞根源:
• 2.x-4.1 系统 searchBoxJavaBridge_、accessibility 等内置接口未移除
• 任意 file:// 协议可跨域,mWebView.loadUrl("javascript:...") 注入
• 意图劫持:js 调用 openApp 后通过 Intent.parseUri 触发 exported 组件
• 信息泄漏:getDeviceId、getInstalledPackages 等敏感接口未做运行时审批 - 国内合规:
• 工信部 164 号文要求 WebView 远程调试端口必须默认关闭
• 《个人信息保护法》要求敏感调用需“双清单”+“弹窗同步” - 加固手段:
• 移除内置接口、setAllowFileAccess(false)、setAllowFileAccessFromFileURLs(false)
• 自定义白名单注解 + 运行时权限检查
• 对 js 入参做 JSON Schema 校验,禁止反射链(getClass、forName、exec)
• 采用 WebViewAssetLoader 或 https 本地缓存,避免 file://
• 线上热修复:WebView 独立进程 + 热更新 SDK(如 Tinker、Sophix)
• 异常日志回捞:结合 Matrix、Sliver 捕获 Java 层与 JS 层堆栈
答案
【最小实现】
- 启用 JavaScript:webView.getSettings().setJavaScriptEnabled(true);
- 定义桥类:
class AndroidBridge {
@JavascriptInterface
public String getToken(String scope) {
// 国内合规:运行时再次检查权限
if (!PrivacyHelper.isUserAuthorized(scope)) {
return "";
}
return TokenManager.getScopedToken(scope);
}
} - 绑定接口:webView.addJavascriptInterface(new AndroidBridge(), "native");
- 前端调用: <script> const token = window.native.getToken('profile'); </script>
【漏洞清单与修复】
- 系统级接口残留:在 onDestroy 中调用 webView.removeJavascriptInterface("searchBoxJavaBridge_") 等;
- file:// 跨域:统一用 WebViewAssetLoader 映射 https://appassets.androidplatform.net;
- 意图劫持:对 openApp 方法内部使用 Intent.parseUri 前先 setComponent(null) 并校验包名签名;
- 敏感数据泄露:getToken 内部接入移动智能终端补充设备标识(OAID)体系,禁止直接返回 IMEI;
- 代码注入:对入参做正则过滤,禁止包含 “getClass”、“Runtime”、“exec” 关键字;
- 远程调试:发布包必须 WebView.setWebContentsDebuggingEnabled(false),通过 BuildConfig.DEBUG 动态开关;
- 回滚策略:若线上发现接口被脱库,通过热更新 SDK 下发空实现,同时上报风控。
拓展思考
- 替代方案:
• 使用 @JavascriptInterface 仅做“信令通道”,业务数据走 WebMessagePort 或 OkHttp 拦截器,实现“JS 只传 ID,Android 回抛结果”的零信任模型;
• 对性能敏感场景(小程序容器)可改用 V8 直接绑定,绕过 WebView 的 Binder 开销。 - 纵深防御:
• 在 Native 层对 libwebviewchromium.so 做二次打包,插入 Inline Hook 检测可疑 JNI 调用;
• 结合 RASP(Runtime Application Self-Protection)对 Java 反射链进行实时熔断。 - 合规趋势:
• 工信部正在征求意见的《移动智能终端应用软件 SDK 安全规范》拟要求“JSBridge 调用必须在隐私政策中逐条列出”,后续需动态生成桥方法列表供用户撤销。