JavaSecurityManagerでセキュリティチェックを実装しようとして問題が発生しました。
セキュリティマネージャのcheckExec()メソッドの目的を誤解しているようです。アプリケーションがコマンドラインから別のJavaアプリケーションを呼び出そうとすると呼び出されると思いましたが、そうではないようです。
これが私がしたいことです:私のカスタムセキュリティマネージャーを使用する呼び出しアプリケーションは、コマンドラインで「javaSomeApp」を実行します。セキュリティマネージャは、これで問題がないかどうかを確認し、適切なアクションを実行します。
これを達成するために、私は次のことを行いました。
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.");
}
}
}
SecurityTest:
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());
}
}
}
InvokeMe:
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が存在するため、その部分は確実に機能しています。