【问题标题】:Java JSSE RMI SSL file gets access deniedJava JSSE RMI SSL 文件被拒绝访问
【发布时间】:2019-04-14 13:47:39
【问题描述】:

对于大学安全实验室工作,我必须使用 RMI 创建一个简单的客户端/服务器应用程序。对于客户端和服务器之间的安全通信,我想使用 SSL。 Oracle has example 所以我尝试使用它。我得到错误。我尝试启动使用 rmi.RMISSLServerSocketFactory.java 的服务器 rmi.HelloImpl.java,其中定义了错误中提到的文件。我收到了这个错误

"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.2.5\lib\idea_rt.jar=54269:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.2.5\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;C:\Users\Agne\IdeaProjects\jssesamples\out\production\jssesamples" rmi.HelloImpl
java.security.AccessControlException: access denied ("java.io.FilePermission" "testkeys" "read")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkRead(SecurityManager.java:888)
    at java.io.FileInputStream.<init>(FileInputStream.java:127)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at rmi.RMISSLServerSocketFactory.<init>(RMISSLServerSocketFactory.java:27)
    at rmi.HelloImpl.main(HelloImpl.java:34)
HelloImpl err: access denied ("java.io.FilePermission" "testkeys" "read")
java.security.AccessControlException: access denied ("java.io.FilePermission" "testkeys" "read")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)

我检查了我的 Java 是 8 版本,我使用 IntelliJ IDEA,我以管理员身份运行它。我也遇到了同样的错误,当我尝试在这段代码中创建文件时,在它进入 testkeys 之前。然后几乎与新文件名相同的错误和访问被拒绝写入。我错过了什么?

以及主要参与的这两个类中的代码:

HelloImpl

package rmi;

import java.io.*;
import java.net.InetAddress;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class HelloImpl extends UnicastRemoteObject implements Hello {

    private static final int PORT = 2019;

    public HelloImpl() throws Exception {
        super(PORT,
              new RMISSLClientSocketFactory(),
              new RMISSLServerSocketFactory());
    }

    public String sayHello() {
        return "Hello World!";
    }

    public static void main(String args[]) {

        // Create and install a security manager
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }

        try {
            // Create SSL-based registry
            Registry registry = LocateRegistry.createRegistry(PORT,
                new RMISSLClientSocketFactory(),
                new RMISSLServerSocketFactory());

            HelloImpl obj = new HelloImpl();

            // Bind this object instance to the name "HelloServer"
            registry.bind("HelloServer", obj);

            System.out.println("HelloServer bound in registry");
        } catch (Exception e) {
            System.out.println("HelloImpl err: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

RMISSLServerSocketFactory

    package rmi;

import java.io.*;
import java.net.*;
import java.rmi.server.*;
import javax.net.ssl.*;
import java.security.KeyStore;
import javax.net.ssl.*;

public class RMISSLServerSocketFactory implements RMIServerSocketFactory {

    /*
     * Create one SSLServerSocketFactory, so we can reuse sessions
     * created by previous sessions of this SSLContext.
     */
    private SSLServerSocketFactory ssf = null;

    public RMISSLServerSocketFactory() throws Exception {
        try {
            // set up key manager to do server authentication
            SSLContext ctx;
            KeyManagerFactory kmf;
            KeyStore ks;

            char[] passphrase = "passphrase".toCharArray();
            ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("testkeys"), passphrase);

            kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, passphrase);

            ctx = SSLContext.getInstance("TLS");
            ctx.init(kmf.getKeyManagers(), null, null);

            ssf = ctx.getServerSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    public ServerSocket createServerSocket(int port) throws IOException {
            return ssf.createServerSocket(port);
    }

    public int hashCode() {
        return getClass().hashCode();
    }

    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        } else if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        return true;
    }
}

【问题讨论】:

  • 摆脱安全管理器。仅当您使用代码库功能时才需要它,而您不需要。

标签: java ssl rmi jsse


【解决方案1】:

安装 RMISecurityManager 后,您需要有一个策略文件来指定您的应用程序在安全策略文件中所需的权限。我认为曾经有一个策略工具应用程序可以帮助您编写该文件,并且错误消息告诉您需要向该文件添加什么权限。在您的情况下,它看起来像:

grant {
    filePermission "testKeys", "read" 
}

需要成为您的安全策略的一部分。

【讨论】:

  • 对我来说它适用于:grant { permission java.security.AllPermission; }; 但出于安全原因,我更喜欢您的解决方案grant { permission java.io.FilePermission "testkeys", "read"; };。唯一的问题,我被拒绝访问Launcher failed - "Dump Threads" and "Exit" actions are unavailable (access denied ("java.io.FilePermission" "C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.2.5\bin\breakgen64.dll" "read")) java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost:2019" "listen,resolve")
  • 您也需要将这些权限添加到文件中......这就是不使用“AllPermission”的问题/功能 - 您可以找出代码需要权限的所有内容做,然后将它们全部添加到策略文件中。 IIRC,我的最终得到了 15-20 条许可行......
  • @moilejter 使用 'AllPermission` 的问题在于,您不妨完全摆脱安全管理器。
猜你喜欢
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 2012-10-17
  • 2015-01-21
  • 2013-09-30
  • 2010-09-15
  • 2015-08-13
  • 2018-05-01
相关资源
最近更新 更多