Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java安全管理器checkExec_Java_Security_Java Security_Java Security Manager_Rapid Prototyping - Fatal编程技术网

Java安全管理器checkExec

Java安全管理器checkExec,java,security,java-security,java-security-manager,rapid-prototyping,Java,Security,Java Security,Java Security Manager,Rapid Prototyping,我在Java安全管理器中实现安全检查时遇到了一个问题 我似乎误解了安全管理器中checkExec()方法的用途。我以为当我的应用程序试图通过命令行调用另一个Java应用程序时,它会被调用,但这似乎没有发生 下面是我想要实现的:使用我的自定义安全管理器的调用应用程序在命令行上执行“javasomeapp”。安全管理器检查这是否正常,并执行适当的操作 为了实现这一点,我做了以下工作: 创建了一个自定义安全管理器,该管理器覆盖checkExec方法。方法签名是public void checkExec

我在Java安全管理器中实现安全检查时遇到了一个问题

我似乎误解了安全管理器中checkExec()方法的用途。我以为当我的应用程序试图通过命令行调用另一个Java应用程序时,它会被调用,但这似乎没有发生

下面是我想要实现的:使用我的自定义安全管理器的调用应用程序在命令行上执行“javasomeapp”。安全管理器检查这是否正常,并执行适当的操作

为了实现这一点,我做了以下工作:

  • 创建了一个自定义安全管理器,该管理器覆盖
    checkExec
    方法。方法签名是
    public void checkExec(String cmd)

  • 创建了一个测试类SecurityTest

  • SecurityTest将我的自定义安全管理器指定为其安全管理器

  • public void checkExec(String cmd) {
        System.out.println(cmd); // prints "java"
        if (cmd.toLowerCase().startsWith("java ") { ... } // is false
        // no security exception is thrown, allowing your command
    }
    
  • SecurityTest然后在命令行上运行
    javainvokeme

  • 自定义安全管理器会截获此消息并执行某些操作

  • 1到4都可以,但5永远不会发生。我已经验证了我的自定义安全管理器是否有效,它是否已成功分配给SecurityTest,SecurityTest是否已成功运行InvokeMe。然而,尽我所能,我的自定义安全管理器中的checkExec()方法从未被调用

    我哪里做错了?我试图做的事情(当应用程序调用
    JavaSomeApp
    时,让安全管理器做一些事情)可能吗

    谢谢你抽出时间

    编辑:

    下面是运行测试的一些代码和输出。这是一种快速原型样式,“拖到后面再清理”样式代码,所以不会很漂亮:

    自定义安全管理器:

    import java.util.*;
    import java.io.*;
    class DTESecurityManager extends SecurityManager {
        // instance variables
    
        DTESecurityManager() {
            super();
            //assign a bunch of variables
            System.out.println("TEST 1");
        }
    
        public void checkExec(String cmd) {
            if (cmd.toLowerCase().startsWith("java ")) {
                if (cmd.matches("(?i).*-djava.security.manager.*")) {
                    throw new SecurityException("Cannot assign a security manager to invoked Java applications.");
                }
                StringBuffer intermediateCommand = new StringBuffer(cmd).insert(5, "-Djava.security.manager=DTESecurityManager ");
                String modifiedCommand = new String(intermediateCommand);
                try {
                    Runtime rt = Runtime.getRuntime();
                    Process pr = rt.exec(modifiedCommand);
                } catch (Exception e) {
                    System.err.println("Error: " + e.getMessage());
                }
                try {
                    FileWriter fstream = new FileWriter("Verification.txt");
                    BufferedWriter out= new BufferedWriter(fstream);
                    out.write("I worked.");
                    out.close();
                } catch (Exception e) {
                    System.err.println("Error: " + e.getMessage());
                }
                throw new SecurityException("Command was executed, but was modified to force invoked application to use this security manager.");
            }
        }
    }
    
    安全测试:

    import java.io.*;
    
    class SecurityTest {
    
        public static void main(String[] args) {
            try {
                System.setSecurityManager(new DTESecurityManager());
            } catch (Exception e) {
                System.out.println("Error: " + e.getMessage());
            }
            try {
                System.out.println("If we got this far, we had no problems setting our security manager.");
                System.out.println("Now let's try to invoke another Java application.");
                Runtime rt = Runtime.getRuntime();
                Process pr = rt.exec("java InvokeMe");
                System.out.println("I reached the end of my test without crashing. Now terminating.");
            } catch (Exception e) {
                System.out.println("Exception message: " + e.getMessage());
            }
        }
    
    }
    
    调用者:

    import java.io.*;
    
    class InvokeMe {
    
        public static void main(String[] args) {
            System.out.println("I, InvokeMe, have been invoked successfully.");
            try {
            FileWriter fstream = new FileWriter("InvokeMeWasCalled.txt");
                BufferedWriter out= new BufferedWriter(fstream);
                out.write("It worked.");
                out.close();
            } catch (Exception e) {
                System.err.println("Error: " + e.getMessage());
            }
        }
    
    }
    
    测试输出:

    TEST 1
    If we got this far, we had no problems setting our security manager.
    Now let's try to invoke another Java application.
    I reached the end of my test without crashing. Now terminating.
    

    没有迹象表明调用了checkExec()——没有控制台输出,我的文件系统中的任何地方都不存在verify.txt。(当然,我不确定执行这样的操作时安全管理器子类的行为应该是什么——所以这可能是正常的。如果是这样的话,我需要另一个快速而肮脏的方法来测试我是否遇到了某些代码行。)InvokeMeWasCalled.txt确实存在,因此,这一部分肯定是有效的。

    问题在于您的安全管理器被覆盖的
    checkExec
    。传递给
    checkExec
    cmd
    参数只包含正在执行的命令中的第一个“单词”,因此在程序中,“java”是
    cmd
    参数。因此,字符串不会以“java”开头,
    checkExec
    不会执行if块,从而导致安全管理器执行“干净”检查

    public void checkExec(String cmd) {
        System.out.println(cmd); // prints "java"
        if (cmd.toLowerCase().startsWith("java ") { ... } // is false
        // no security exception is thrown, allowing your command
    }
    

    另外,作为旁注,修改后的命令执行将导致一个
    StackOverflowerError
    ,因为只有第一个“单词”被传递给该方法。

    我知道代码并不漂亮,但它似乎使用了黑名单方法,即“如果我们认识到这是一个不需要的模式,那么我们抛出一个异常。”这对于现实世界来说不够健壮,而且它与实际问题有关(“cmd”不是指您认为它做了什么)


    首先,在“if”块之后,如果我们不想做一些特殊的事情,应该有“else super.checkExec()”来运行常规处理。这就解决了您的问题。

    听起来您做得不错,而且您尝试做的是可能的,这让我相信这可能是代码问题。你能举个测试的例子吗?当然可以。我已经编辑了我的问题,包括相关的代码和测试输出。做了一些调试,我发现了问题;参考我贴出的答案。我学到了一些新东西
    cmd
    只是命令中空格前的第一个字符串。如果可以使用StringBuilder,请不要使用StringBuffer。几乎没有什么好的理由起诉StringBuffer。是的,这就是问题所在。这就解开了这个谜。我想如果我想强制我的程序使用某个安全管理器调用其他程序,我必须找到一种更聪明的方法来实现它。。。