先来了解下常见的网络劫持:
dns劫持(域名劫持)
现象就是用户不能访问目的网址或访问的是假网址。http劫持
现象就是用户访问的看到的页面可能是被恶意修改过的,比如常见的在底部弹出宣传性的广告或者直接某网站的内容。本质是在正常的数据流中插入精心设计的网络数据报文,目的是让用户端程序解释“错误”的数据。
以前做的一款App,今天被客户方投诉在上海地区出现了打开网页后接着跳转某赌博App的appstore页面或展示了宣传赌博app的网页。看了客户方提供的视频,发现是先展示出了目的页面后面才发生的跳转错误页,很明显这不是dns劫持而是http劫持了。
发生劫持的M站的确是使用的http协议,发生事故后客户方目前已在部署ssl证书着手改为https协议(披着ssl安全协议的http)。
今天我想讲的是,如果针对的是数据流中添加了跳转恶意链接的劫持行为的话,作为webview载体方来说,还是可以稍微做一下拦截的。
记得在之前写的文章《h5 App通信 轻量级方式》中就提到过这个api:
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String urlConection) {
if (urlConection.toLowerCase().startsWith("http:") || urlConection.toLowerCase().startsWith("https:")) {
//TODO host白名单限制
webview.loadUrl(urlConection);
return true;
}
return true;
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return super.shouldOverrideUrlLoading(view, request);
}
java 截取url中host的方法
public static String getHost(String url){
Pattern pattern = Pattern.compile("^http[s]?:\\/\\/(.*?)([:\\/]|$)");// 匹配的模式
Matcher m = pattern.matcher(url);
while (m.find()) {
return m.group(1);
}
return "";
}
在正则表达式中:
(pattern)
=》匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到。
.
=> 匹配除“\n”和"\r"之外的任何单个字符
*
=> 匹配前面的子表达式任意次,等价于{0,}。
?
=> 匹配前面的子表达式零次或一次,等价于{0,1}。
注:当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']
代码分析:
正则表达式 "^http[s]?:\\/\\/(.*?)([:\\/]|$)"
getHost("http://www.baidu.com:8090/path?y=90&https://www1.baidu.com:8090/path?y=39&https://www2.baidu.com:8090/path?y=19")
m.group(0) 输出 http://www.baidu.com:
m.group(1) 输出 www.baidu.com
m.group(2) 输出 :
根据以上我们可以看出Matcher的group方法,入参的Index的意义:
Index为0 ,代表符合匹配的整体字符串
Index为1 ,代表符合第一个子匹配的字符串 正则中第一个()
Index为2 ,代表符合第二个子匹配的字符串 正则中第二个()
有了上面的方法后,我们就能采用一些白名单限制的措施了。
不在白名单内的话, 就直接return true 不执行webview.loadUrl。
再提供下js的写法
let reg = /http[s]?:\/\/(.*?)([:\/]|$)/
let result=reg.exec(getUrl)
let whiteUrl = [ 'xx', 'xxx', 'xxx']
let flag=0;// 是否在白名单内
if(result){
for(let i=0,l=whiteUrl.length;i<l;i++){
if(whiteUrl[i]==result[1]){
flag=1;
break;
}
}
}