You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Thymeleaf中禁用静态上下文及方法调用,保障自定义模板安全?

Restricting Thymeleaf to Safe, User-Customizable Templates

Absolutely, you can lock down Thymeleaf to exactly the safe subset of features you need—blocking arbitrary Java method calls, static member access, and only allowing basic conditionals, loops, and object field access. Here's how to implement this effectively:

1. Control Expression Evaluation (Core of the Restriction)

Thymeleaf uses either SpringEL (in Spring environments) or OGNL (standalone) for evaluating expressions. The key is to customize the evaluation context to filter out unsafe operations.

For Spring-Based Applications (SpringEL)

Override the evaluation context in your SpringTemplateEngine configuration to block unwanted method calls and static access:

@Bean
public SpringTemplateEngine safeTemplateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setTemplateResolver(yourTemplateResolver());

    // Customize the SpringStandardDialect to enforce security rules
    engine.addDialect(new SpringStandardDialect() {
        @Override
        public IEvaluationContext createEvaluationContext(
                IExpressionContext expressionContext,
                IProcessingContext processingContext) {
            StandardEvaluationContext context =
                    (StandardEvaluationContext) super.createEvaluationContext(expressionContext, processingContext);

            // Block all method calls except getter/is methods (for field access)
            context.setMethodFilter((method, target) -> {
                String methodName = method.getName();
                // Allow standard getter methods (getXxx()) and boolean isXxx() methods
                return (methodName.startsWith("get") && method.getParameterCount() == 0)
                        || (methodName.startsWith("is") && method.getParameterCount() == 0);
            });

            // Block ALL static method access
            context.setStaticMethodFilter(method -> false);

            // Block static field access
            context.addPropertyAccessor(new BeanWrapperPropertyAccessor() {
                @Override
                public boolean canRead(EvaluationContext ctx, Object target, String name) throws AccessException {
                    // Prevent accessing static fields like T(java.lang.System).out
                    if (target instanceof Class) {
                        return false;
                    }
                    return super.canRead(ctx, target, name);
                }
            });

            return context;
        }
    });

    return engine;
}

For Standalone Thymeleaf (OGNL)

If you're not using Spring, configure OGNL's security manager to restrict access:

TemplateEngine safeTemplateEngine = new TemplateEngine();
safeTemplateEngine.setTemplateResolver(yourTemplateResolver());

// Custom OGNL parser with security rules
OGNLExpressionParser expressionParser = new OGNLExpressionParser();
expressionParser.setOgnlContextFactory((ctx, processingCtx) -> {
    OgnlContext ognlContext = (OgnlContext) Ognl.createDefaultContext(ctx);
    
    ognlContext.setSecurityManager(new OgnlSecurityManager() {
        // Allow only getter/is methods for instance objects
        @Override
        public boolean isMethodAccessAllowed(Object target, Method method, Object[] args) {
            String methodName = method.getName();
            return (methodName.startsWith("get") && method.getParameterCount() == 0)
                    || (methodName.startsWith("is") && method.getParameterCount() == 0);
        }

        // Block all static method calls
        @Override
        public boolean isStaticMethodAccessAllowed(Class<?> clazz, Method method, Object[] args) {
            return false;
        }

        // Allow instance field access (optional, for direct field access instead of getters)
        @Override
        public boolean isFieldAccessAllowed(Object target, Field field) {
            return true;
        }

        // Block all static field access
        @Override
        public boolean isStaticFieldAccessAllowed(Class<?> clazz, Field field) {
            return false;
        }
    });

    return ognlContext;
});

safeTemplateEngine.setExpressionParser(expressionParser);

2. Enforce Template Syntax Constraints

Even with expression restrictions, add an extra safety layer by validating user templates during upload/save:

  • Allow only core attributes: th:if, th:each, th:text, th:switch, th:case, th:with (basic flow control and data rendering)
  • Reject any attributes that could execute arbitrary logic (though the expression rules already mitigate this, validation adds redundancy)

You can use Thymeleaf's TemplateParser to parse templates programmatically and flag forbidden attributes.

3. Test Edge Cases

Validate your setup with these critical scenarios:

  • Arbitrary method calls: ${user.someCustomMethod("unsafe")} should throw an exception or be blocked
  • Static access: ${T(java.lang.Math).random()} or ${T(java.lang.System).out} should be rejected
  • Valid field access: ${user.name} (via getName()) or ${user.isActive()} should work as expected

内容的提问来源于stack exchange,提问作者Daniël V

火山引擎 最新活动