防止JVM写入System.out或从System.in读取

时间:2014-08-14 19:24:31

标签: java security io permissions jvm

JVM下是否有办法(暂时)阻止对System.out,System.in和System.err的完全访问?

创建一个根本不授予权限的空白策略后,我想在下面的函数中执行一些工作。 我希望调用System.out.println之类的功能失败,但他们不会。我有什么可以做的,或者我是一个太多的控制狂?

编辑#1:根据MrPixelDream建议使用System.setOut,我将权限保持在最低限度,以确保run()中的代码也无法调用System.setOutjava.io.FileDescriptor.out愚弄。

编辑#2 另外,由于流氓代码可能只是简单地执行了standardOutput.println,因此我倾向于不保留对System.out的引用,并将其设置为使用java.io.FileDescriptor.out

// Create blank permissions that barely allow executing code
java.security.Permissions perm = new java.security.Permissions();

// CodeSource domain for which these permissions apply (all files)
java.security.CodeSource code = new java.security.CodeSource(new java.net.URL("file:/*"),
                                                             null);

// ProtectionDomain
java.security.ProtectionDomain domain = new java.security.ProtectionDomain(code, perm);

// AccessControlContext
java.security.ProtectionDomain[] domains = new java.security.ProtectionDomain[1];
domains[0] = domain;

java.security.AccessControlContext context =
  new java.security.AccessControlContext(domains);

// DON'T keep reference to standard output, it could be used directly
// PrintStream standardOut = System.out;

// Redirect output to dummy stream
System.setIn(new ByteArrayInputStream(new byte[0]));
System.setOut(new PrintStream(new ByteArrayOutputStream()));
System.setErr(new PrintStream(new ByteArrayOutputStream()));

// Do an action, subject to the given security context
java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {

  public Void run() {

    // Do some work, side effects and all, but no I/O whatsoever
    System.out.println("Will not print !");

    // Try to fool around System.out with direct access from file descriptors (0, 1, 2)
    java.io.PrintStream myOut =
      new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out));

    // Missing permission java.lang.RuntimePermission "setIO"
    // Will throw java.security.AccessControlException
    System.setOut(myOut);

    // Missing permission java.lang.RuntimePermission "writeFileDescriptor"
    myOut.println("Will throw java.security.AccessControlException !");

  }

}, context);

// Now set back the old streams to have output again
System.setIn(new java.io.FileInputStream(java.io.FileDescriptor.in));
System.setOut(
  new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out)));
System.setErr(
  new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.err)));

2 个答案:

答案 0 :(得分:2)

Elliott Frisch的答案可以解决问题,但是你做完之后就无法获得输出。如果您打算暂时将输出静音,请使用以下代码:

public class RedirectedOutput {

    public static void main(String[] args) {
        // Save the old output stream to have the chance to set it back later
        InputStream standardIn  = System.in;
        PrintStream standardOut = System.out;
        PrintStream standardErr = System.err;

        // Set useless streams
        System.setIn(new ByteArrayInputStream(new byte[0]));
        System.setOut(new PrintStream(new ByteArrayOutputStream()));
        System.setErr(new PrintStream(new ByteArrayOutputStream()));

        // Will not be shown
        System.out.println("Hello World");

        // Now set back the old streams to have output again
        System.setIn(standardIn);
        System.setOut(standardOut);
        System.setErr(standardErr);

        // Will be shown again
        System.out.println("Finally we got the Hello");
    }

}

您可以尝试这个应该完全可运行的示例。它应该是自我解释的。您正在使用setIn()setOut()setErr()来更改流,然后将其保存,然后才能将其设置回来。

但如果您不需要任何输出,那么您最好使用Elliott的代码,因为我觉得它对资源更好。

答案 1 :(得分:1)

我不相信有一种方法可以暂时执行此操作,但您可以阻止它们写入或读取,直到JVM重新启动close()它们之类的内容,

public static void main(String[] args) {
    try {
        System.in.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.err.close();
    System.out.close();
    System.out.println("Must not print !");
}

没有输出。