首页 > 解决方案 > java.policy 授予 SocketPermission 时,为什么 ServerSocket.accept() 上出现 AccessControlException?

问题描述

尽管在 java.policy 中授予了 SocketPermission,但在 ServerSocket.accept() 上会引发 AccessControlException。

出于编校目的,假设服务器 IP 地址为 1.2.3.4,客户端 IP 地址为 5.6.7.8。

服务器上的 java.policy 有一个授权。

grant codeBase "file:C:/workspaces/gitlab/QMT-beachhead/QMT-beachhead/lib/-"{
  permission java.net.SocketPermission "5.6.7.8:1024-", "accept";
};

同样的效果已经尝试了其他几种方式:

permission java.net.SocketPermission "5.6.7.8", "accept";
permission java.net.SocketPermission "5.6.7.8:*", "accept";
permission java.net.SocketPermission "5.6.7.8:0", "accept";

最近的尝试在驱动器号之前添加了缺少的斜杠。

file:/C:/workspaces/gitlab/QMT-beachhead/QMT-beachhead/lib/-

所有结果都类似于:

java.security.AccessControlException 访问被拒绝 ("java.net.SocketPermission" "5.6.7.8:50838" "accept,resolve")

服务器端错误信息中的端口,被理解为客户端表达式client.getLocalPort()的返回值,每次都不一样。

在服务器上,

private java.net.ServerSocket server;
private java.net.Socket connection;

try {
  connection = server.accept();
  }
catch (SecurityException e) {
  System.err.println(e.getClass().getName() + " " + e.getMessage());
}

在客户端

private java.net.Socket client;
private java.io.ObjectInputStream input;

try {
  byte[] addr = {(byte)1, (byte)2, (byte)3, (byte)4};
  client = new java.net.Socket(java.net.InetAddress.getByAddress(addr), 16838);
  java.io.InputStream is = client.getInputStream();
  input = new ObjectInputStream(is);
}
  catch (java.io.IOException e) {
  System.err.println(e.getClass().getName());
}

实际结果是服务器上的 java.security.AccessControlException 而 accept 方法阻塞,而客户端上的 java.io.EOFException 从 java.io.InputStream 实例化 ObjectInputStream 时,这是一个 java.net.SocketInputStream。虽然 EOFException 是从 ObjectInputStream 构造函数中抛出的,但触发服务器的 AccessControlException 的是客户端的 Socket 实例。

预期的结果是服务器的 java.policy 中的 java.net.SocketPermission 授权被理解,没有 AccessControlException 并且在客户端从 java.io.InputStream 实例化 ObjectInputStream,这是一个 java.net.SocketInputStream,是成功的。

标签: java

解决方案


像这样的权限条目没有任何问题

permission java.net.SocketPermission "5.6.7.8:1024-", "accept";

codeBase 值需要更多关注。1.2.3.4 的所有者已验证代码源位置在目录树中

C:\workspaces\gitlab\QMT-beachhead\QMT-beachhead\lib\

那里有一些代码,但需要 SocketPermission 的代码在目录树中

C:\workspaces\gitlab\QMT-beachhead\QMT-beachhead\bin\

此外,根据https://docs.oracle.com/javase/8/docs/technotes/guides/security/PolicyFiles.html#FileSyntax上的文档,驱动器号之前需要一个斜杠。codeBase 字段变为

codeBase "file:/C:/workspaces/gitlab/QMT-beachhead/QMT-beachhead/bin/-"

推荐阅读