我们想使用标准的 Android WebView 作为沙箱来执行本地 HTML/JS 应用程序。一个主要的安全需求是将 WebView 设置为完全离线,并且只允许调用某些 javascript 接口(interface)。这些接口(interface)使用 WebView.addJavascriptInterface() 方法传递到 javascript 运行时。
Android应用本身有访问网络的权限(android.permission.INTERNET)。
我能够禁用正常的 http/https 请求,但完全无法阻止 WebSocket 请求。这些处理方式似乎与普通的 http 请求不同。
一种替代方法是覆盖 WebSocket JavaScript 方法。但这让我感觉很糟糕,因为它违背了沙盒概念。似乎也可以使用 delete恢复原来的函数指针。
另一种选择是将自己定制的 WebView(例如 Crosswalk-Project)与我们的应用程序 bundle 在一起,但希望避免这种情况,因为编译和更新非常费力。
我尝试了以下公共(public) WebView 接口(interface),但它们似乎都无法阻止 WebSocket 调用:
- webSettings.setBlockNetworkLoads(true);
- webSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
- webView.setNetworkAvailable(false);
- WebViewClient.shouldOverrideUrlLoading()(回调)
- WebViewClient.shouldInterceptRequest()(回调,两个版本都试过了)
- WebChromeClient.onPermissionRequest()
在 Android 4.4.4 (19) 和 Android 5/5.1 (21/22) 上测试。
我正在执行的 javascript:
ws = new WebSocket("wss://echo.websocket.org");
ws.onmessage = function(event) {
console.log("received: " + event.data);
};
ws.onclose = function() {
console.log("External Socket closed");
};
ws.onopen = function() {
console.log("Connected to external ws");
ws.send("Hello from " + navigator.userAgent);
};
知道如何做到这一点吗?
非常感谢
最佳答案
不幸的是,目前还没有办法在 WebView 中拦截 WebSockets 调用。您只能阻止整个 JavaScript 执行或网络访问。你是对的,尝试用你自己的实现覆盖 WebSocket
构造函数可以通过删除被覆盖的 window 属性轻松解决,因此内置构造函数可从 window
原型(prototype)访问链再次可见。如果您尝试使用 WebView.addJavascriptInterface
覆盖 WebSocket
,也会发生同样的情况。
我认为,HTML Application Cache 也不会被 WebView 回调拦截,甚至不需要打开 Javascript 即可工作。
我想,您使用系统 WebView 创建 WebView 网络沙箱的唯一机会是使用没有网络访问权限的专用应用程序,并使用 Binder IPC 与其通信。 .
bundle 自定义 WebView 会带来更多困难,因为您需要找出并堵上所有漏洞,然后继续使用您自己的安全修复程序对其进行更新。
关于javascript - 强制 Android WebView 离线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30325836/