Thymeleaf异常处理Calling methods is forbidden for type

2023-05-01 10:07:39 浏览数 (3)

版本

thymeleaf 3.0.15

现象

在thymeleaf模板中通过${session.SPRING_SECURITY_LAST_EXCEPTION.getMessage()}获取异常消息时报错

Caused by: org.springframework.expression.EvaluationException: Calling methods is forbidden for type ‘java.lang.RuntimeException’ in Thymeleaf expressions. Blacklisted classes are: [java.util.concurrent.RunnableFuture, java.util.concurrent.Executor, java.lang.Runtime, java.util.concurrent.FutureTask, java.util.concurrent.ListenableFuture, java.lang.Runnable, java.util.concurrent.Future, java.lang.Thread, java.lang.reflect.Executable, java.lang.Class, java.lang.ClassLoader, java.sql.DriverManager].

原因

在thymeleaf 3.0.15中将java.lang.Runtime前缀的类加入了黑名单不允许在模板中访问

解决

异常以Exception抛出不要以RuntimeException抛出,其他类似问题通解

源码

  • 包thymeleaf-spring5-3.0.15

org.thymeleaf.spring5.expression.ThymeleafEvaluationContext

代码语言:javascript复制
static final class ThymeleafEvaluationContextACLMethodResolver extends ReflectiveMethodResolver {

        ThymeleafEvaluationContextACLMethodResolver() {
            super();
        }

        @Override
        public MethodExecutor resolve(
                final EvaluationContext context, final Object targetObject,
                final String name, final List<TypeDescriptor> argumentTypes) throws AccessException {

            final Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
            // 判断对象是否时允许访问的类型
            if (!ExpressionUtils.isTypeAllowed(type.getName())) {
                // We will only specifically allow calling "Object.getClass()" and "Class.getName()"
                if (!(Class.class.equals(type) && "getName".equals(name))
                        && !(Object.class.equals(type) && "getClass".equals(name))) {
                    throw new EvaluationException(
                            String.format(
                                    "Calling methods is forbidden for type '%s' in Thymeleaf expressions. "  
                                    "Blacklisted classes are: %s.",
                                    type.getName(), ExpressionUtils.getBlacklist()));
                }
            }
            return super.resolve(context, targetObject, name, argumentTypes);
        }

    }
  • 包thymeleaf-3.0.15 org.thymeleaf.util. ExpressionUtils
代码语言:javascript复制
public final class ExpressionUtils {
	// 所有黑名单类名前缀
    private static final Set<String> BLOCKED_CLASS_NAME_PREFIXES =
            new HashSet<String>(Arrays.asList(
                    "java.lang.Runtime", "java.lang.Thread", "java.lang.Class", "java.lang.ClassLoader",
                    "java.lang.Runnable", "java.lang.reflect.Executable",
                    "java.util.concurrent.Future", "java.util.concurrent.FutureTask",
                    "java.util.concurrent.RunnableFuture", "java.util.concurrent.ListenableFuture",
                    "java.util.concurrent.Executor",
                    "java.sql.DriverManager"));

    public static boolean isTypeAllowed(final String typeName) {
        Validate.notNull(typeName, "Type name cannot be null");
        final int i0 = typeName.indexOf('.');
        if (i0 >= 0) {
            final String package0 = typeName.substring(0, i0);
            if ("java".equals(package0)) { // This is the only prefix that might be blocked
                for (final String prefix : BLOCKED_CLASS_NAME_PREFIXES) {
                    if (typeName.startsWith(prefix)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
    public static List<String> getBlockedClasses() {
        final List<String> blocked = new ArrayList<String>();
        blocked.addAll(BLOCKED_CLASS_NAME_PREFIXES);
        return blocked;
    }
    private ExpressionUtils() {
        super();
    }
}

1 人点赞