一种URLHost校验方式学习

一种URL Host校验方式学习

方法概述

在APP测试的过程中发现了一种URL Host的权限校验方式,检测的方法与EndWith检测类似,但是更加的灵活;通过对特定的XML文件解析得到URL Scheme和URL Host的白名单,并通过自定义PermissionManager类中的校验策略完成校验;个人感觉这种校验的方式具有比较好的灵活性可以做为一个良好的URL Host检测模板。

详细说明

整个URL Host的校验可以分为两个大部分,一个是对URL Host的存储和提取,另一个是自定义校验方式,下面将从这两个部分分别说明实现的形式;

XML的存储和解析

下面是XML的部分内容,URL Host的白名单会作为整个APP配置文件中的一部分,一起存储在config.xml文件中。通过不同格式的XML解析可以提取出这个部分并形成一个Permission List进行管理

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="com.miui.hahahaha" version="0.0.1">
<access origin="http://duokanbox.com" subdomains="true"/>
<access origin="https://duokanbox.com" subdomains="true"/>
<access origin="http://mi.com" subdomains="true"/>
<access origin="https://mi.com" subdomains="true"/>
<access origin="http://xiaomi.com" subdomains="true"/>
<access origin="https://xiaomi.com" subdomains="true"/>
</widget>

可以看到每条数据包含两个内容:

  • origin : 用于记录URL Scheme和URL host
  • subdomains :用于规定是否允许其子域名通过校验

XML中记录的白名单会通过XmlResourceParser完成解析并形成下面这种Config类(只节选了关于PermissionManager的片段)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Config {
private Map<String, Permission> permissions = new HashMap();

public Map<String, Permission> getPermissions() {
return this.permissions;
}

public void addPermission(Permission permission) {
this.permissions.put(permission.getUri(), permission);
}
}


public class Permission {
private boolean applySubdomains;
private boolean forbidden;
private String uri;

public String getUri() {
return this.uri;
}

public void setUri(String str) {
this.uri = str;
}

public boolean isApplySubdomains() {
return this.applySubdomains;
}

public void setApplySubdomains(boolean z) {
this.applySubdomains = z;
}

public boolean isForbidden() {
return this.forbidden;
}

public void setForbidden(boolean z) {
this.forbidden = z;
}
}

PermissionManager 权限校验部分

首先贴一下PermissionManager的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class PermissionManager {
private Config mConfig;
private Map<String, Boolean> mValidMap = new HashMap(); //用于记录检测过的域名状态


public PermissionManager(Config config) {
this.mConfig = config;
}

private boolean initPermission(String str) {
String str2;
String str3;
Uri parse = Uri.parse(str);
if ("myscheme".equals(parse.getScheme())) {
//在这里可以自定义对于某些特殊协议的处理方式;
//也可以对与不同的协议分开来检验;
str2 = "*";
} else {
str2 = parse.getHost();
}
boolean z = false;
for (Entry value : this.mConfig.getPermissions().entrySet()) {
Permission permission = (Permission) value.getValue();
String uri = permission.getUri();
if ("*".equals(uri)) {
str3 = "*";
} else {
str3 = Uri.parse(uri).getHost();
}
if (permission.isApplySubdomains()) {
//对于允许子域名校验的情况,按照"."分割域名,从后向前依次检测;
String[] split = str3.split("\\.");
String[] split2 = str2.split("\\.");
if (split2.length >= split.length) {
int i = 1;
while (true) {
if (i > split.length) {
z = true;
break;
} else if (!split2[split2.length - i].equals(split[split.length - i])) {
z = false;
break;
} else {
i++;
}
}
} else {

}
} else {
z = str2.equals(str3);
}
if (z) {
break;
}
}
return z;
}

public boolean isValid(String str) {
if (!this.mValidMap.containsKey(str)) {
this.mValidMap.put(str, Boolean.valueOf(initPermission(str)));
}
return ((Boolean) this.mValidMap.get(str)).booleanValue();
}
}

该class中包含两个属性:

  • Config mConfig : XML文件经过解析以后形成的class,在对象创建的时候初始化
  • Map<String, Boolean> mValidMap : 记录经过校验的URL的状态方便下次查询

两个方法 :

  • isValid : 查询HashMap中是否已经记录了URL的信息,如果没有则调用initPermission来检测,并记录在HashMap中;
  • initPermission : 完成具体的URL Host检测的过程;

总结