Apache JEXL从3.2.1升级到3.3后测试失败,如何安全适配?
解决JEXL 3.3升级后测试失败的问题(无需使用UNRESTRICTED权限)
JEXL 3.3默认启用了RESTRICTED权限策略,这和3.2.1默认无限制的行为差异很大——即使你配置了沙箱允许方法调用,权限层仍会拦截未明确放行的操作。你的测试失败就是因为默认权限阻止了两个关键操作:命名空间sns下的静态方法currentTimeMillis调用,以及上下文对象result的实例方法set调用。
解决方案:自定义权限策略,仅放行需要的操作
你不需要用UNRESTRICTED这种全局开放的配置,而是通过JexlPermissions.Builder精准放行测试中用到的方法:
- 构建自定义权限,明确允许命名空间的静态方法和上下文对象的实例方法调用
- 替换掉
JexlPermissions.UNRESTRICTED,使用自定义权限
修改后的完整测试代码如下:
@Test public void testUsingWhiteSandbox() { // given JexlSandbox sandbox = new JexlSandbox(false); sandbox.allow(System.class.getName()).execute("currentTimeMillis"); sandbox.allow(AtomicLong.class.getName()).execute("set"); Map<String, Object> namespaces = new HashMap<>(); namespaces.put("sns", System.class); // 自定义权限:仅放行需要的操作 JexlPermissions permissions = new JexlPermissions.Builder() // 允许命名空间sns下的currentTimeMillis静态方法 .allow(JexlPermissions.NAMESPACE, "sns:currentTimeMillis") // 允许上下文对象result的set实例方法 .allow(JexlPermissions.CONTEXT, "result.set") .build(); JexlEngine jexl = new JexlBuilder() .sandbox(sandbox) .namespaces(namespaces) .strict(true) .silent(false) // 替换为自定义权限,去掉UNRESTRICTED .permissions(permissions) .create(); AtomicLong atomicLong = new AtomicLong(); MapContext context = new MapContext(); context.set("result", atomicLong); long now = System.currentTimeMillis(); //when jexl.createScript("result.set(sns:currentTimeMillis())").execute(context); // then AtomicLong result = (AtomicLong) context.get("result"); assertThat(result.get()).isGreaterThanOrEqualTo(now); }
更灵活的权限配置(可选)
如果需要放行同一类的多个方法,也可以用通配符简化配置:
- 放行
sns命名空间下的所有静态方法:.allow(JexlPermissions.NAMESPACE, "sns:*") - 放行所有上下文对象的
set方法:.allow(JexlPermissions.CONTEXT, "*.set") - 放行AtomicLong类的所有实例方法:
.allow(JexlPermissions.CONTEXT, "result.*")
这样既能保证测试通过,又能维持较高的安全性,避免全局开放权限带来的风险。
内容的提问来源于stack exchange,提问作者abdel
相关产品推荐
相关产品推荐

