为什么要禁用URL Scheme
和Universal Link
(通用链接)
通常我们APP中都会嵌套一些web页面,有时我们的web页面会被DNS劫持从而跳转到其他APP中;或者是某些APP的Universal Link
(通用链接)设置的比较容易触发,当web跨域跳转就有可能跳转到这些APP。比如苏宁易购的Universal Link
(通用链接)为*.m.suning.com
,只要web进行跨域跳转*.m.suning.com
就会拉起苏宁易购APP。在这种情况下的话我们就需要在我们的APP中对web做一些处理从而来禁止拉起这些APP。
在iOS 9.0之后如果需要使用URL Scheme
唤起APP的话需要在info.plist中增加白名单,只有在白名单中的URL Scheme
才可以使用,因此可以禁止跳转到意料之外的APP。
<key>LSApplicationQueriesSchemes</key>
<array>
<string>openapp.jdmobile</string>
</array>
WKWebView
在iOS8.0后APP推出的WKWebView
是现有大部分APP中常用的控件之一。
-
WKWebView
中URL Scheme
禁用和启用即使在info.plist中设置了白名单但是
WKWebView
对URL Scheme
默认是不支持的,如果要支持URL Scheme
需要做一些处理- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL *url = navigationAction.request.URL;
// 调用电话
if ([url.scheme isEqualToString:@"tel"]) {
if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
decisionHandler(WKNavigationActionPolicyAllow);
} -
WKWebView
中Universal Link
(通用链接)禁用对于
Universal Link
(通用链接)的话因为该方式是通过系统层级来直接拉起APP的,在WKWebView
也是可以无缝跳转的。如果需要禁用Universal Link
(通用链接)的话只需要在WKNavigationDelegate
的- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
中WKNavigationActionPolicyAllow
替换成WKNavigationActionPolicyAllow+2
:- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
decisionHandler(WKNavigationActionPolicyAllow+2);
}
UIWebView
虽然iOS8.0后提供了WKWebView
,但是如果需要手动管理cookie
的话(WKWebView
在iOS11.0之后才可以手动管理cookie
)或其他原因还是又很大一部分使用UIWebView
的APP。
-
UIWebView
中URL Scheme
禁用
在iOS9.0之后对于UIWebView
只有URL Scheme
配置在info.plist中才可以正常使用,因此对URL Scheme
不需要做特殊处理。
在iOS 9.0之前在UIWebView
中禁用URL Scheme
需要我们在- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
代理方法中做一些处理。
首先我们可以依然设置白名单列表,例如:self.whiteSchemes = @[@"http",@"https"];
当跳转的Scheme
不在我们的白名单中就禁止跳转:- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = request.URL;
if (![self.whiteSchemes containsObject:url.scheme]) {
return NO;
}
return YES;
} -
UIWebView
中Universal Link
(通用链接)禁用
其实在APP中嵌套的web页面大部分都是自己家的页面,因此域名应该是固定的。因此在UIWebView
中禁用Universal Link
(通用链接)我只想到用最笨的方法和禁用URL Scheme
方式一样。
设置白名单列表,但是和白名单列表中存放的是host
(域名)而不是Scheme
,例如:self.whiteHosts = @[@"http",@"https"];
。当跳转的不是白名单中的话就直接禁止跳转。- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = request.URL;
if (![self.whiteHosts containsObject:url.host]) {
return NO;
}
return YES;
}
文章若有不对地方,欢迎批评指正