如何验证JS脚本仅在白名单原生App的WebView中运行?
核心结论:无法直接通过JS获取应用商店唯一App ID
WebView作为网页与原生App的隔离层,系统不会主动向网页JS暴露应用商店ID(比如iOS的Bundle ID对应App Store ID、Android包名对应Google Play ID这类原生专属标识)。要实现JS代码仅在指定原生App中运行,必须通过原生App主动向WebView提供可信标识,再结合后台校验完成验证。
具体可行验证方案
1. 原生注入自定义可信标识
原生App初始化WebView时,主动向JS上下文注入约定好的唯一标识(比如你方给合作方分配的专属密钥、App的包名/Bundle ID),示例如下:
- iOS(WKWebView):通过
WKUserScript注入全局变量let script = WKUserScript(source: "window.appAuthKey = 'YOUR_ASSIGNED_UNIQUE_KEY';", injectionTime: .atDocumentStart, forMainFrameOnly: true) webView.configuration.userContentController.addUserScript(script) - Android(WebView):通过
evaluateJavascript注入webView.evaluateJavascript("window.appAuthKey = 'YOUR_ASSIGNED_UNIQUE_KEY';", null);
JS端逻辑:页面加载时读取window.appAuthKey,将其与合作方密钥一起传给后台,后台校验该标识是否在授权白名单中,且合作方状态活跃。
注意:为防止标识被伪造,建议对标识做签名处理——原生端用约定密钥对标识+时间戳生成签名,JS将标识、时间戳、签名一起传给后台,后台验证签名有效性后再校验白名单。
2. 自定义WebView的User-Agent
原生App修改WebView的User-Agent,加入专属标识,比如在原有UA末尾追加; AppAuthId=XXX。JS端通过navigator.userAgent读取UA,提取出AppAuthId后传给后台校验。
缺点:User-Agent容易被篡改,不建议单独使用,最好结合签名校验或其他方案。
3. 原生JS桥接动态授权验证
定义JS与原生的交互方法,让原生返回带签名的动态授权令牌,流程如下:
- JS调用原生方法(比如
window.getAppAuthToken()) - 原生端生成包含App唯一标识、有效期的令牌,并用约定密钥签名
- JS拿到令牌后,传给你的后台
- 后台验证令牌的签名、有效期,以及标识是否在授权列表中
这种方式安全性最高,令牌是动态生成的且有效期短,即使被窃取也难以复用。
避坑提醒
不要依赖WebView的默认属性(比如部分Android WebView的UA可能包含包名)做验证,这类属性没有统一标准,不同系统版本、WebView实现可能存在差异,且容易被篡改。只有原生主动提供、双方约定好的可信标识,结合后台校验,才能保证验证的可靠性。
内容的提问来源于stack exchange,提问作者LWSChad

