我在尝试在 Java 安全管理器中实施安全检查时遇到问题。
我似乎误解了安全管理器中 checkExec() 方法的用途。我认为当我的应用程序尝试通过命令行调用另一个 Java 应用程序时它会被调用,但这似乎并没有发生。
这就是我想要发生的事情:使用我的自定义安全管理器的调用应用程序在命令行上执行“java SomeApp”。安全管理器检查这是否正常并执行适当的操作。
为了做到这一点,我做了以下事情:
创建了一个覆盖该
checkExec
方法的自定义安全管理器。方法签名是public void checkExec(String cmd)
.创建了一个测试类,SecurityTest。
SecurityTest 将我的自定义安全管理器指定为其安全管理器。
SecurityTest 然后
java InvokeMe
在命令行上运行。自定义安全管理器拦截了这一点并做一些事情。
1 到 4 很好,但 5 永远不会发生。我已验证我的自定义安全管理器有效,它已成功分配给 SecurityTest,并且 SecurityTest 成功运行了 InvokeMe。但是,据我所知,我的自定义安全管理器中的 checkExec() 方法永远不会被调用。
我哪里错了?我正在尝试做的事情(让安全管理器在应用程序调用时做某事java SomeApp
)甚至可能吗?
感谢您的时间。
编辑:
这是运行测试产生的一些代码和输出。这是快速原型风格,“先把它搞定,以后再清理”风格的代码,所以它不会很漂亮:
自定义安全管理器:
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() 被调用——没有控制台输出,并且 Verification.txt 在我的文件系统上的任何地方都不存在。(当然,我不确定在执行此类操作时安全管理器子类的行为应该是什么——所以这可能是正常的。如果是这种情况,我需要另一种快速而简单的方法来测试我是否'我打了某些代码行。) InvokeMeWasCalled.txt 确实存在,所以这部分肯定是有效的。