Javaで #appengine のようなサンドボックス環境を作る場合、SecurityManagerを使用するのがよさそうです。
http://itref.fc2web.com/java/security.html
具体的には、ポリシーファイルというものを書くという形になります。
(以下は転載)
grant {
permission java.util.PropertyPermission "test_prop", "write,read";
permission java.io.FilePermission "c:/temp/test.txt", "read,write";
//permission java.io.FilePermission "<>", "read,write";
};
しかし、今時のWebアプリなら、実行環境ごとに設定をお願いするのではなく、warをデプロイするだけで、必要な設定はなされていてくれる方がありがたいです。また、policyファイルのような外部ファイルを使うのではなく、純粋にJavaだけで制御すればデバッガもろもろが使えて便利ですよね?
policyファイルを使用しない方法は、java.lang.SecurityManager を独自にオーバーライドすることで実現できます。
http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/SecurityManager.html
そして、こんな感じにします。
public class MySecurityManager extends SecurityManager { @Override public void checkExit(int status) { throw new SecurityException("system exit is not supported."); } }
System.setSecurityManager(new MySecurityManager());
しかし、これだと、環境にセキュリティーマネージャが設定されている場合は、その実装が殺されてしまいます。ということは、セキュリティーが考慮された環境でこれを行った場合、ヘタをすると、セキュリティーを低下させてしまいかねません。
※もちろん、よく設定された環境では、セキュリティマネージャの設定自体が許されない可能性もあります。
そう思うと気が重いことです。なかなか手をつけられません。
そこで、既存のセキュリティマネージャを生かしつつ、独自のセキュリティーチェックをJavaだけで実装しようとする場合は、以下のようにすれば良さそうです。
public class NullSecurityManager extends SecurityManager { @Override public void checkPermission(Permission perm, Object context) { // なにもしない } @Override public void checkPermission(Permission perm) { // なにもしない } }
public class MySecurityManager extends NullSecurityManager { private SecurityManager innerSecurityManager; public MySecurityManager(SecurityManager innerSecurityManager) { if (innerSecurityManager == null) { innerSecurityManager = new NullSecurityManager(); } this.innerSecurityManager = innerSecurityManager; } @Override public void checkPermission(Permission perm) { innerSecurityManager.checkPermission(perm); } @Override public void checkPermission(Permission perm, Object context) { innerSecurityManager.checkPermission(perm, context); } @Override public void checkCreateClassLoader() { innerSecurityManager.checkCreateClassLoader(); } public void checkExit(int status) { innerSecurityManager.checkExit(status); throw new SecurityException("system exit is not supported."); } // 以下あらゆるメcheck系メソッドを委譲 }
あとは、Servletの起動時に
try { SecurityManager securityManager = System.getSecurityManager(); if (!(securityManager instanceof MySecurityManager)) { System.setSecurityManager(new MySecurityManager(securityManager)); } } catch (SecurityException e) { System.out.println("cannot set my SecurityManager"); }
こんな感じで動きました。