基本上,我有一个GUI,允许用户编写和执行Groovy脚本。 GroovyShell通过SecureASTCustomizer编译器配置进行保护。 我有一个类,比如说RandomClass ,我希望用户能够通过变量helper进行访问。 该代码必须是静态编译的,因此我们可以在尝试执行之前检查脚本的有效性。 但是, 在此阶段 ,我只关心编译脚本 。 计划是检查脚本是否有效,例如
helper.someMethod()
静态编译它,然后在以后将变量helper加载到GroovyShell的绑定中动态评估该脚本的文本。
首先,通过使用CompileStatic批注的扩展脚本,将helper变量识别为RandomClass类型。 编译成功如果setIndirectImportCheckEnabled()的的SecureASTCustomizer被设置为假,然而,它允许用户以解决安全性,如def c = System; c.exit(-1) def c = System; c.exit(-1) ,它将在不发出安全警告的情况下进行编译。 启用间接导入检查后,当我尝试执行helper.someMethod()时,代码将不再编译,因为出于某种原因将helper视为对象。
RandomClass.java
class RandomClass
{
public RandomClass(){}
public void someMethod(){}
}
扩展脚本
unresolvedVariable { var ->
if ('helper'==var.name) {
storeType(var, classNodeFor(RandomClass))
handled = true
}
}
主要方法
Map params = new HashMap<>();
params.put( "extensions", "robot.groovy" );
ImportCustomizer imports = new ImportCustomizer().addImports("com.package.RandomClass" );
ASTTransformationCustomizer cust = new ASTTransformationCustomizer( params , CompileStatic.class);
SecureASTCustomizer secure = new SecureASTCustomizer();
secure.setImportsWhitelist( Arrays.asList( "com.package.RandomClass" ) );
secure.setStaticImportsWhitelist( Arrays.asList() );
secure.setStaticStarImportsWhitelist( Arrays.asList() );
secure.setReceiversClassesWhiteList(Arrays.asList(RandomClass.class))
CompilerConfiguration cc = new CompilerConfiguration();
cc.addCompilationCustomizers( cust, secure, imports );
GroovyShell shell = new GroovyShell( cc );
1. shell.parse("helper.someMethod()" // should compile
2. shell.parse("System.exit(-1)") // should not compile
3. shell.parse("def c = System; c.exit(-1)") // should not compile
如果我将接收器类设置为包括Object,则1个编译,2个失败,但3个仍然编译。
如果我添加间接导入检查,则所有3个都将失败。 第一个失败, Importing [java.lang.Object] is not allowed 。 即使我们在扩展脚本中将类型设置为RandomClass,我也很难弄清楚在调用对象时助手如何变成对象。