请考虑以下代码段:
(在本例中为OpenJDK 6b24-1.11.5-0ubuntu1~12.10.1,由于所有JVM 6和7都与Oracle和OpenJDK具有相同的行为,因此看似无关紧要)
SocketPermission toCheck = new SocketPermission("www.google.ca", "resolve");
SocketPermission checker = new SocketPermission("*.ca:80", "connect");
System.out.println("Result: " + checker.implies(toCheck));
checker = new SocketPermission("*.1e100.net:80", "connect");
System.out.println("Result: " + checker.implies(toCheck));
我得到的结果是:
Result: false
Result: true
问题似乎是JVM执行反向查找以验证地址是否与已解析的域实际匹配。
www.google.ca域名的挖掘查找显示以下内容:
[rotty@rotty-desktop ~]$ dig www.google.ca ANY
; <<>> DiG 9.8.1-P1 <<>> www.google.ca ANY
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48015
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.google.ca. IN ANY
;; ANSWER SECTION:
www.google.ca. 114 IN A 74.125.226.55
www.google.ca. 114 IN A 74.125.226.56
www.google.ca. 114 IN A 74.125.226.63
www.google.ca. 74 IN AAAA 2607:f8b0:400b:801::1018
;; Query time: 27 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Mon Jan 14 17:18:50 2013
;; MSG SIZE rcvd: 107
此外,获取结果中的第一个地址并执行DNS查找会产生:
[rotty@rotty-desktop ~]$ nslookup 74.125.226.55
Server: 127.0.1.1
Address: 127.0.1.1#53
Non-authoritative answer:
55.226.125.74.in-addr.arpa name = yyz06s06-in-f23.1e100.net.
Authoritative answers can be found from:
这似乎清楚地表明了这个问题。非权威性反向查找返回为域定义的第一个(在本例中为locality)别名。
这意味着我需要知道并声明可能解析为指定域名的基础地址的任何潜在别名。
为什么JVM需要这样的匹配?实际上,地址确实存在的简单验证不足以解决&#34;解决问题。过程要满足?地址可能有任意数量的可能反向映射。这怎么可能在实践中发挥作用?
[更新] 为了澄清这实际上与默认的Java策略定义相同,请考虑以下附加示例:
Socket socket = new Socket("www.google.ca", 80);
socket.close();
将以下安全策略应用于上述内容:
grant {
permission java.net.SocketPermission "*.ca:80", "connect";
//permission java.net.SocketPermission "*.1e100.net:80", "connect";
};
执行程序为:
java -Djava.security.manager -Djava.security.policy=../security.policy Test
结果:
Exception in thread "main" java.security.AccessControlException: access denied ("java.net.SocketPermission" "www.google.ca" "resolve")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
at java.security.AccessController.checkPermission(AccessController.java:560)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkConnect(SecurityManager.java:1048)
at java.net.InetAddress.getAllByName0(InetAddress.java:1203)
at java.net.InetAddress.getAllByName(InetAddress.java:1127)
at java.net.InetAddress.getAllByName(InetAddress.java:1063)
at java.net.InetAddress.getByName(InetAddress.java:1013)
at java.net.InetSocketAddress.<init>(InetSocketAddress.java:142)
at java.net.Socket.<init>(Socket.java:208)
at example.security.SocketSecurityExample.test(SocketSecurityExample.java:13)
at example.security.SocketSecurityExample.main(SocketSecurityExample.java:9)
将政策文件更改为:
grant {
//permission java.net.SocketPermission "*.ca:80", "connect";
permission java.net.SocketPermission "*.1e100.net:80", "connect";
};
正确执行代码的结果。
答案 0 :(得分:-1)
连接时JVM不会执行该操作。它构造一个包含实际主机名/ IP地址的SocketPermission,并使用'implies'来检查.policy文件中的任何权限是否暗示该权限。