翻譯自:securitymanager
Intro
在 Java 中可以用 sun.misc.Unsafe 類為所欲為。而 SecurityManager 就像是一個(gè)保護(hù)裝置,幫助你阻止某些敏感動(dòng)作(io,網(wǎng)絡(luò),反射,訪問等)。
SecurityManager manager = System.getSecurityManager();
if (manager != null) {
manager.checkAction(action);
}
如果某個(gè)動(dòng)作是不被允許的,那么會(huì)拋出 SecurityExeption。
Use Case
假設(shè)我們正在構(gòu)建 在線評(píng)分 程序,該程序接受 java 代碼,運(yùn)行代碼,取出結(jié)果并且驗(yàn)證結(jié)果是否正確。
顯然,運(yùn)行不受信的代碼是不安全的。因此,我們需要確認(rèn)代碼提交者不會(huì)中斷/危及整個(gè)評(píng)分系統(tǒng)。例如,某個(gè)提交者可以讀取密碼修改數(shù)據(jù)庫中的評(píng)分項(xiàng)。又或者更壞地,耗盡整個(gè)文件系統(tǒng),RAM 或消耗所有線程以至于無法為其他提交者評(píng)分。
** SecurityManager ** 解決這些問題。
擴(kuò)展這個(gè)類并覆蓋所需要的策略,指明什么是允許的,什么是不允許的。
class MySecurityManager extends SecurityManager {
@Override
public void checkRead(FileDescriptor fd) {
throw new SecurityException("File reading is not allowed");
}
@Override
public void checkWrite(FileDescriptor fd) {
throw new SecurityException("File writing is not allowed");
}
@Override
public void checkConnect(String host, int port) {
throw new SecurityException("Socket connections are not allowed");
}
}
可以在運(yùn)行時(shí)這樣設(shè)置security manager:
System.setSecurityManager(new MySecurityManager());
Note: setSecurityManager 同樣也可以用 security manager 控制。
如果某個(gè)的受限制的動(dòng)作被執(zhí)行,那么會(huì)拋出 SecurityException。
Inspect methods fromSecurityManager which starts with check prefix. There are plenty of checks JVM may run before your code.
盡管,security manager 對(duì)于配置子系統(tǒng)的訪問,阻止不受信的代碼做錯(cuò)誤的事情十分好用,但是有些動(dòng)作并不受 security manager 的控制。
Memory Allocation
內(nèi)存分配并不受編程人員控制,同樣 SecurityManager 也不限制對(duì)象的創(chuàng)建。如果你需要校驗(yàn)不受信的代碼是否滿足內(nèi)存要求,可以在另一個(gè) JVM 上執(zhí)行,并給定該 JVM 最大的內(nèi)存使用量 java -Xmx128m。如果超出內(nèi)存要求,那么會(huì)拋出 OutOfMemory 異常。
對(duì)于更精確的內(nèi)存管理,你需要附加 instrumentation agent 到 java 進(jìn)程。
Threads
并沒有什么方式用來限制 java 進(jìn)程派生出的線程個(gè)數(shù)。如果只使用 ExecutorService 來創(chuàng)建線程,那么可以通過使用 ExecutorService.newFixedThreadPool(limit) 來限制線程個(gè)數(shù)。
否則,你需要編寫一個(gè)自定義的 agent 跟蹤活動(dòng)線程的個(gè)數(shù)。?
Timeouts
保證某個(gè)算法可以在指定間隔內(nèi)完成,需要使用一些外部的工具為其設(shè)置一個(gè)超時(shí)時(shí)間。linux 下可以使用 coreutils。
Libraries
可以通過使用 SecurityManager.checkPackageAccess 阻止使用某整個(gè)包。同樣,也可以從整個(gè)架構(gòu)上阻止使用某些外部的庫或產(chǎn)品。但是,如果你想要阻止使用某些特定的方法,例如 java.lang.Math.min() 那么你可能需要手動(dòng)掃描 java 源文件,并檢測(cè)這樣的調(diào)用。