如何验证Groovy文本是简单值而非Groovy脚本并实现类型转换?
安全解析Groovy风格的基本类型与数组
不用GroovyShell.evaluate()执行代码,我们可以通过解析Groovy抽象语法树(AST)的方式,安全提取基本类型及基本类型数组的值,完全避免代码执行风险。以下是具体实现方案:
核心思路
利用Groovy的AstBuilder将输入的字符串解析为语法树节点,然后只允许处理数字字面量、字符串字面量、仅包含上述类型的数组字面量,拒绝任何可执行的代码节点(比如表达式、方法调用等),从而安全转换为对应类型。
实现代码
import org.codehaus.groovy.ast.expr.* import org.codehaus.groovy.control.CompilerConfiguration def safeParseParam(String param) { def config = new CompilerConfiguration() config.scriptBaseClass = groovy.lang.Script.name try { // 解析输入为AST节点,仅做语法分析不执行代码 def ast = new AstBuilder().parse(script: param, compilerConfiguration: config) if (ast.size() != 1 || !(ast[0] instanceof Expression)) { throw new IllegalArgumentException("输入不是合法的单个字面量表达式") } return parseExpression(ast[0]) } catch (Exception e) { throw new IllegalArgumentException("不支持的输入类型或语法错误", e) } } def parseExpression(Expression expr) { switch (expr) { case IntLiteral: return expr.value case LongLiteral: return expr.value case StringLiteral: return expr.value case ListExpression: // 递归解析数组元素,确保仅包含基本类型 return expr.expressions.collect { elemExpr -> parseExpression(elemExpr) } default: throw new IllegalArgumentException("不支持的表达式类型: ${expr.class.simpleName}") } } // 测试示例 def testInputs = [ "[56, 23, 56]", '["asdf", "qwer"]', '"aswqer"', "89" ] testInputs.each { input -> try { def result = safeParseParam(input) println "输入: $input → 解析结果: $result (类型: ${result.class.simpleName})" } catch (Exception e) { println "输入: $input → 错误: ${e.message}" } }
说明
- 安全性:
AstBuilder仅做语法解析,不会执行任何代码,通过限制允许的节点类型,彻底杜绝代码注入风险。 - 支持类型:自动识别并转换
int、long、String,以及由这些类型组成的数组。 - 错误处理:如果输入是Groovy可执行代码(如
1+2、println('test'))或非法语法,会直接抛出异常。
如果需要支持更多基本类型(如float、boolean),只需在parseExpression方法中添加对应的字面量节点判断即可。
内容的提问来源于stack exchange,提问作者Dean Hiller
相关产品推荐
相关产品推荐

