2.10 自定义安全管理器
About 475 wordsAbout 2 min
2021-03-27
2.10 自定义安全管理器
所有模板的本地调用都需要通过安全管理器校验,默认需要实现NativeSecurityManager 的public boolean permit(String resourceId, Class c, Object target, String method) 方法
如下是Beetl3.17版本后默认的白名单管理器,只允许java.util包的Java调用
public class WhiteListNativeSecurityManager implements NativeSecurityManager {
Pattern callPattern = null;
public WhiteListNativeSecurityManager(){
allow(Arrays.asList("java.util"));
}
@Override
public boolean permit(Object resourceId, Class c, Object target, String method) {
if (c.isArray()) {
// 允许调用,但实际上会在在其后调用中报错。不归此处管理
return true;
}
String name = c.getName();
int i = name.lastIndexOf('.');
if (i == -1) {
// 无包名,肯定安全,允许调用
return true;
}
return callPattern.matcher(name).matches();
}
}
可以自定义安全管理器,或者调用allow方法添加更多允许的Java调用
WhiteListNativeSecurityManager securityManager = new WhiteListNativeSecurityManager();
securityManager.allow(Arrays.asList("java.util","com.mycorp.project.util","com.mycorp.project.constants.Constants));
在Beetl3.17版本之前,默认使用的是DefaultNativeSecurityManager,他采用黑名单管理方式,杜绝了目前已知的漏洞(但不保证未来有安全漏洞)如下是默认管理器的实现方法
public class DefaultNativeSecurityManager implements NativeSecurityManager{
@Override
public boolean permit(String resourceId, Class c, Object target, String method){
if (c.isArray()){
//允许调用,但实际上会在在其后调用中报错。不归此处管理
return true;
}
String name = c.getSimpleName();
String pkg = c.getPackage().getName();
if (pkg.startsWith("java.lang")){
if (name.equals("Runtime") || name.equals("Process") || name.equals("ProcessBuilder")
|| name.equals("System")){
return false;
}
}
//省略其他安全漏洞屏蔽代码
return true;
}
}
需要强调的是,当允许在Beetl模板中使用Java本地调用,且使用DefaultNativeSecurityManager,且Beetl的模板编写权利交给浏览器终端用户,才有可能发生安全漏洞,这跟Struts框架,Spring框架,JSON工具的漏洞原因是一样的,但发生几率相比这些Web框架来说,几乎不可能,就好比如果把Java编写编译的权利交给浏览器终端用户,那Java也有安全漏洞