Skip to content

Commit d1e212a

Browse files
author
lemon
committed
全局安全检查完善:注入bridge的时候,如果没有通过安全校验,则移除注入的bridge对象
1 parent 4236884 commit d1e212a

File tree

5 files changed

+79
-17
lines changed

5 files changed

+79
-17
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/src/main/assets/demo.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,19 @@
2121
function toast(params = 'toast data') {
2222
window.easyBridge.callHandler('toast', 'toast with:' + params + 'at ' + new Date().toLocaleString());
2323
}
24+
25+
function jumpToPage(){
26+
var url=document.getElementById('tv_url').value;
27+
window.open(url);
28+
}
2429
</script>
2530
</head>
2631

2732
<body>
2833

34+
<input type="text" value="http://google.com" id="tv_url">
35+
<input type="button" value="jump" onclick="jumpToPage()">
36+
2937
<a href="javascript:toast('click toast')">
3038
<h3>测试Toast</h3>
3139
</a>

app/src/main/java/easily/tech/easybridge/MainActivity.kt

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package easily.tech.easybridge
22

3+
import android.net.Uri
34
import android.os.Build
45
import android.support.v7.app.AppCompatActivity
56
import android.os.Bundle
6-
import android.webkit.WebChromeClient
7-
import android.webkit.WebView
7+
import android.webkit.*
88
import android.widget.Toast
99
import easily.tech.easybridge.handler.ToastHandler
1010
import easily.tech.easybridge.lib.EasyBridgeWebChromeClient
1111
import easily.tech.easybridge.lib.ResultCallBack
12-
import easily.tech.easybridge.lib.SecurityPolicyChecker
1312
import kotlinx.android.synthetic.main.activity_main.*
1413

1514
class MainActivity : AppCompatActivity() {
@@ -20,7 +19,27 @@ class MainActivity : AppCompatActivity() {
2019
WebView.setWebContentsDebuggingEnabled(true)
2120
}
2221
setContentView(R.layout.activity_main)
22+
webView.webViewClient = object : WebViewClient() {
23+
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
24+
return false
25+
}
26+
}
27+
// set a global security checker,all the url with scheme https/http is not allowed to using the bridge
28+
webView.setPolicyChecker(({ url, parameters ->
29+
val page = Uri.parse(url)
30+
when (parameters) {
31+
// control the bridge inject action
32+
EasyBridgeWebChromeClient.SECURITY_CHECK_PARAMETERS -> when (page.scheme) {
33+
"http" -> false
34+
"https" -> false
35+
else -> true
36+
}
37+
else -> true
38+
}
39+
}))
40+
2341
webView.registerHandler(ToastHandler(this))
42+
2443
webView.loadUrl("file:///android_asset/demo.html")
2544
// call JavaScript From Java
2645
webView.postDelayed({
@@ -32,4 +51,12 @@ class MainActivity : AppCompatActivity() {
3251
})
3352
}, 5000)
3453
}
54+
55+
override fun onBackPressed() {
56+
if (webView.canGoBack()) {
57+
webView.goBack()
58+
} else {
59+
super.onBackPressed()
60+
}
61+
}
3562
}

easybridge/src/main/java/easily/tech/easybridge/lib/EasyBridgeWebChromeClient.java

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,12 @@ public class EasyBridgeWebChromeClient extends WebChromeClient {
1010

1111
private static final String BRIDGE_SCRIPT_PATH = "easybridge.js";
1212
private static final String JAVA_SCRIPT_PROTOCOL = "javascript:";
13-
14-
15-
protected SecurityPolicyChecker securityPolicyChecker;
16-
13+
public static final String SECURITY_CHECK_PARAMETERS = "inject bridge script";
1714
private boolean isInjected;
1815
private EasyBridgeWebView easyBridgeWebView;
1916

2017
public EasyBridgeWebChromeClient(EasyBridgeWebView webView) {
2118
this.easyBridgeWebView = webView;
22-
this.securityPolicyChecker = webView.getPolicyChecker();
2319
}
2420

2521
@Override
@@ -28,13 +24,29 @@ public void onProgressChanged(WebView view, int newProgress) {
2824
// inject the bridge code when the progress above 25% to make sure it worked
2925
if (newProgress <= 25) {
3026
isInjected = false;
31-
} else if (!isInjected) {
32-
if (securityPolicyChecker == null || securityPolicyChecker.check(view.getUrl(), "")) {
27+
return;
28+
}
29+
if (!isInjected) {
30+
// TODO: 2018/4/3 it seems that the url received here possibly not the same as the real page url we look forward to
31+
if (easyBridgeWebView.checkSecurityGlobally(view.getUrl(), SECURITY_CHECK_PARAMETERS)) {
3332
isInjected = true;
34-
String bridgeScript = Utils.readAssetFile(view.getContext(), BRIDGE_SCRIPT_PATH);
35-
String executeScript = "var bridgeName = " + "\"" + easyBridgeWebView.getBridgeName() + "\"" + ";" + bridgeScript;
36-
view.loadUrl(String.format("%s%s", JAVA_SCRIPT_PROTOCOL, executeScript));
33+
injectBridge(view);
34+
} else {
35+
deleteBridge(view);
3736
}
3837
}
3938
}
39+
40+
private void injectBridge(WebView view) {
41+
String bridgeScript = Utils.readAssetFile(view.getContext(), BRIDGE_SCRIPT_PATH);
42+
String executeScript = "var bridgeName = " + "\"" + easyBridgeWebView.getBridgeName() + "\"" + ";" + bridgeScript;
43+
view.loadUrl(String.format("%s%s", JAVA_SCRIPT_PROTOCOL, executeScript));
44+
}
45+
46+
private void deleteBridge(WebView view) {
47+
// execute script below to remove the bridge had set before :
48+
// delete _easybridge;
49+
String script = "delete " + EasyBridgeWebView.MAPPING_JS_INTERFACE_NAME + ";";
50+
view.loadUrl(String.format("%s%s", JAVA_SCRIPT_PROTOCOL, script));
51+
}
4052
}

easybridge/src/main/java/easily/tech/easybridge/lib/EasyBridgeWebView.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@
1010
import easily.tech.easybridge.lib.handler.BridgeHandler;
1111

1212
/**
13+
* this class is the main entrance of the library,you are supposed to do things as bellow:
14+
* 1. register handler that to be call by JavaScript:{@link #registerHandler(BridgeHandler)}
15+
* 2. set a global security checker:{@link #setPolicyChecker(SecurityPolicyChecker)}
16+
* before inject a bridge,you will receive a check request with the parameters:{@link EasyBridgeWebChromeClient#SECURITY_CHECK_PARAMETERS},make your idea about it;
17+
* 3. you can make a global security check by:{@link #checkSecurityGlobally(String, String)}
18+
* 4. you can call the JavaScript function with:{@link #callHandler(String, String, ResultCallBack)},
19+
* but make sure before:you had register a JavaScript handler using the bridge,the code is like below:
20+
* "window.easyBridge.registerHandler(handlerName,realFunction)"
21+
* <p>
1322
* Created by lemon on 29/03/2018.
1423
*/
1524
public class EasyBridgeWebView extends WebView {
1625

17-
private static final String MAPPING_JS_INTERFACE_NAME = "_easybridge";
26+
static final String MAPPING_JS_INTERFACE_NAME = "_easybridge";
1827
private static final String DEFAULT_BRIDGE_NAME = "easyBridge";
1928
private final EasyBridge easyBridge;
2029
private String bridgeName = DEFAULT_BRIDGE_NAME;
@@ -79,10 +88,16 @@ public String getBridgeName() {
7988
return bridgeName;
8089
}
8190

82-
public SecurityPolicyChecker getPolicyChecker() {
83-
return policyChecker;
91+
public boolean checkSecurityGlobally(String url, String parameters) {
92+
return policyChecker == null || policyChecker.check(url, parameters);
8493
}
8594

95+
/**
96+
* make sure that ,the instance {@link SecurityPolicyChecker} set here is working globally,
97+
* if the security checked failed ,the bridge is not allowed to using (it will remove the bridge inner)
98+
*
99+
* @param policyChecker a global {@link SecurityPolicyChecker} instance
100+
*/
86101
public void setPolicyChecker(SecurityPolicyChecker policyChecker) {
87102
this.policyChecker = policyChecker;
88103
}

0 commit comments

Comments
 (0)