我对groovy很新,并且通常在java中编写脚本,而且我真的
希望我的问题有一个简单的解决方案。
在我们的应用程序中,用户可以执行他们编写的groovy脚本
他们自己,我们需要控制那些脚本可以做什么和不能做什么。
我读了很多关于沙盒groovy的东西,但我要么看
错误的地方或我忽略了显而易见的。
为简单起见,我有一个小例子来说明问题。
这是我的类加载器,它应该阻止java.lang.System
加载并可用于脚本:
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("java.lang.System")) {
throw new ClassNotFoundException("Class not found: " + name);
}
return super.loadClass(name);
}
}
这是一个试图调用System.currentTimeMillis()
的简单程序:
public static void main(String[] args) {
String code = "java.lang.System.currentTimeMillis();";
ClassLoader classLoader = new MyClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
GroovyShell shell = new GroovyShell();
Script script = shell.parse(code);
Object result = script.run();
log.debug(result);
}
MyClassLoader
会抛出java.lang.SystemBeanInfo
的例外情况
和java.lang.SystemCustomizer
,但代码执行。
如果我使用javax.script
类,也会发生同样的事情:
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("Groovy");
Object o = engine.eval(code);
log.debug(o);
如果我尝试使用JavaScript引擎,它会按预期工作(只需替换 &#34; Groovy的&#34;使用&#34; JavaScript&#34;在上面的例子中。)
任何人都可以帮我吗?顺便说一下,我使用的是groovy-all-1.8.8.jar jdk1.7.0_55。
由于
答案 0 :(得分:3)
我可以为此目的推荐Groovy Sandbox。与SecureASTCustomizer
相反,它将检查在运行时是否允许动态执行。它拦截每个方法调用,对象分配,属性/属性访问,数组访问等等 - 因此您可以对允许的内容(白名单)进行非常精细的控制。
当然,允许的配置非常重要。例如,您可能希望允许使用String
并使用substring
之类的方法,但可能不使用execute
上的String
方法,这可能会被'rm -R ~/*'.execute()
之类的方法利用。 1}}。
创建一个非常安全的配置是一项挑战,而且越多,您就越难以实现。
Groovy Sandbox的缺点是代码必须在注册的拦截器上运行,并且在执行期间会有性能损失。
此图像[1]显示了一个项目示例,其中我们使用Groovy Sandbox for Groovy代码输入。运行代码来修改脚本 - 所以如果那里的语句实际上是作为其中的一部分执行的,那么应用程序将在我可以执行屏幕截图之前退出;)
答案 1 :(得分:2)
也许您有兴趣将SecureASTCustomizer
与CompilerConfiguration
结合使用。如果您担心安全问题,明确的白名单可能比黑名单更好。
def s = new SecureASTCustomizer()
s.importsWhiteList = [ 'a.legal.Klass', 'other.legal.Klass' ]
def c = new CompilerConfiguration()
c.addCompilationCustomizers(s)
def sh = new GroovyShell(c)
看看那个类,它包含许多可以使用的选项。
答案 2 :(得分:0)
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
public class SandboxGroovyClassLoader extends ClassLoader {
public SandboxGroovyClassLoader(ClassLoader parent) {
super(parent);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("java.lang.System"))
return null;
return super.loadClass(name);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (name.startsWith("java.lang.System"))
return null;
return super.loadClass(name, resolve);
}
static void runWithGroovyClassLoader() throws Exception {
System.out.println("Begin runWithGroovyClassLoader");
String code = "def hello_world() { java.lang.System.currentTimeMillis(); };";
GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
Class<?> scriptClass = groovyClassLoader.parseClass(code);
Object scriptInstance = scriptClass.newInstance();
Object result = scriptClass.getDeclaredMethod("hello_world", new Class[] {}).invoke(scriptInstance, new Object[] {});
System.out.println(result);
groovyClassLoader.close();
System.out.println("End runWithGroovyClassLoader");
}
static void runWithSandboxGroovyClassLoader() throws Exception {
System.out.println("Begin runWithSandboxGroovyClassLoader");
ClassLoader parentClassLoader = SandboxGroovyClassLoader.class.getClassLoader();
SandboxGroovyClassLoader classLoader = new SandboxGroovyClassLoader(parentClassLoader);
String code = "def hello_world() { java.lang.System.currentTimeMillis(); };";
GroovyClassLoader groovyClassLoader = new GroovyClassLoader(classLoader);
Class<?> scriptClass = groovyClassLoader.parseClass(code);
Object scriptInstance = scriptClass.newInstance();
Object result = scriptClass.getDeclaredMethod("hello_world", new Class[] {}).invoke(scriptInstance, new Object[] {});
System.out.println(result);
groovyClassLoader.close();
System.out.println("End runWithSandboxGroovyClassLoader");
}
static void runWithSandboxGroovyShellClassLoader() throws Exception {
System.out.println("Begin runWithSandboxGroovyShellClassLoader");
String code = "java.lang.System.currentTimeMillis();";
ClassLoader parentClassLoader = SandboxGroovyClassLoader.class.getClassLoader();
SandboxGroovyClassLoader classLoader = new SandboxGroovyClassLoader(parentClassLoader);
Thread.currentThread().setContextClassLoader(classLoader);
GroovyShell shell = new GroovyShell();
Script script = shell.parse(code);
Object result = script.run();
System.out.println(result);
System.out.println("End runWithSandboxGroovyShellClassLoader");
}
public static void main(String[] args) throws Exception {
runWithGroovyClassLoader();
runWithSandboxGroovyClassLoader();
runWithSandboxGroovyShellClassLoader();
}
}
这是你想要的吗?