截至目前,您可能已经了解到Jakarta EE 9的努力,旨在为EE创新提供新的基础。
Jakarta EE 9是建立在EE 8之上的迭代发布,其主要目的是将所有javax.
包重命名为jakarta.
包。
在一段时间内,我们将为EE 8和EE 9提供等效的Hibernate Validator版本:Hibernate Validator 6.x将保留javax.
包,而Hibernate Validator 7.x将迁移到jakarta.
包。
考虑到许多库都依赖于javax.*
包,Java生态系统的全面过渡可能需要数月甚至数年,这就是为什么我们将并行维护两者,也是为什么今天发布两个新版本的原因。
总结一下
-
如果您正在使用
javax.*
包,本公告的6.2部分适用于您, -
如果您正在过渡到Jakarta EE 9和
jakarta.*
包,则应使用7.0版本。
关于使用javax.*
包或jakarta.*
包的一致性很重要,因此只有当您可以将整个堆栈迁移到Jakarta EE 9时,才升级到Hibernate Validator 7。
如果不能,应继续使用Hibernate Validator 6.x。
这些是候选发布版,请与您的应用程序一起测试它们,并报告反馈。 最终发布版很快就会到来。 |
7个具体更改
Hibernate Validator 7是Jakarta Bean Validation 3的参考实现,它是Jakarta EE 9的一部分。
这意味着它使用jakarta.validation
包。
此外,XML配置文件的命名空间已更改
-
https://jakarta.ee/xml/ns/validation/configuration
是配置的新命名空间(即validation.xml
)。
再次强调,只有当您想将整个堆栈迁移到Jakarta EE 9时,才升级到7。
7和6.2中的新功能
表达式语言
在Hibernate Validator中,为了正确地插入所有内置约束消息,您需要在类路径中包含一个表达式语言实现,因为一些默认消息使用了表达式语言功能。
这些消息是您代码的一部分,因此表达式语言插入这些消息不是问题。
问题是当通过ConstraintValidatorContext
创建自定义违规(使用消息模板)时,这些消息也会被表达式语言引擎插入。
在大多数情况下这是安全的。但如果你在消息模板中包含用户输入,你需要格外小心,因为你需要使用addExpressionVariable()
来转义用户输入。
我们已经在下面讨论了与此相关的CVE:[链接](https://blog.hibernate.com.cn/2020/05/07/hibernate-validator-615-6020-released/)。当时我们决定这是一个正常的行为,与SQL注入非常相似:你需要在编写SQL时以类似的方式转义你的参数。我们还使现有文档更清晰,并使警告更加突出。
我们最近收到了一个报告,称一个常用库没有注意到这一点。这引发了我们之前忽略的另一个问题:没有符合规范的解决方案来保证安全。唯一保证安全的方法是使用Hibernate Validator特定的API。这意味着它不是实现无关的,如果你计划同时支持Hibernate Validator和Apache BVal,可能会出现问题。
这使得我们重新考虑了这种情况,并决定在Hibernate Validator中彻底改变处理表达式语言的方式,主要变化如下:
-
默认情况下,表达式语言对于自定义违规(即您从
ConstraintValidatorContext
创建的)是禁用的。 -
您可以逐个案例启用它,这意味着您可以为特定的自定义违规启用EL,同时保持安全。
-
默认情况下,也不再允许在您的表达式中调用bean方法。您可以访问bean属性,但不能调用bean方法。
-
您可以分别调整您希望为约束和自定义违规启用的EL功能。
我们引入了表达式语言功能级别的概念,它定义了哪些表达式语言引擎功能被启用。
我们目前接受四个功能级别的值
-
NONE
:完全禁用表达式语言插入。 -
VARIABLES
:允许通过addExpressionVariable()
、资源包和formatter
对象使用注入的变量进行插入。 -
BEAN_PROPERTIES
:允许VARIABLES
允许的一切,以及bean属性的插入。 -
BEAN_METHODS
:还允许执行bean方法。对于硬编码的约束消息可以认为是安全的,但对于需要额外注意的自定义违规则不安全。
BEAN_PROPERTIES
是约束的默认值。
NONE
是自定义违规的默认值。如果没有指定功能级别而本地启用,它将使用VARIABLES
功能级别。
以下示例显示了如何为自定义违规启用表达式语言
public class SafeValidator implements ConstraintValidator<ZipCode, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if ( value == null ) {
return true;
}
HibernateConstraintValidatorContext hibernateContext = context.unwrap(
HibernateConstraintValidatorContext.class );
hibernateContext.disableDefaultConstraintViolation();
if ( isInvalid( value ) ) {
hibernateContext
.addExpressionVariable( "validatedValue", value )
.buildConstraintViolationWithTemplate( "${validatedValue} is not a valid ZIP code" )
.enableExpressionLanguage() (1)
.addConstraintViolation();
return false;
}
return true;
}
private boolean isInvalid(String value) {
// ...
return false;
}
}
1 | 使用自定义违规的默认功能级别启用表达式语言支持:VARIABLES 。 |
请注意,如果需要,您可以定义更宽松的功能级别。但请非常小心,并在将用户输入包含到您的消息模板中时使用addExpressionVariable()
。
您可以在文档中了解更多关于这些内容
虽然绝对不推荐,但您可以通过使用我们文档本段末尾描述的两个属性,不修改代码就回到之前的行为。
获取 6.2.0.CR1
要使用 Maven、Gradle 等获取发布版本,请使用 GAV 坐标 org.hibernate.validator:{hibernate-validator|hibernate-validator-cdi|hibernate-validator-annotation-processor}:6.2.0.CR1。请注意,组 ID 已从 org.hibernate
(Hibernate Validator 5 及之前版本)更改为 org.hibernate.validator
(从 Hibernate Validator 6 开始)。
获取 7.0.0.CR1
要使用 Maven、Gradle 等获取发布版本,请使用 GAV 坐标 org.hibernate.validator:{hibernate-validator|hibernate-validator-cdi|hibernate-validator-annotation-processor}:7.0.0.CR1。请注意,组 ID 已从 org.hibernate
(Hibernate Validator 5 及之前版本)更改为 org.hibernate.validator
(从 Hibernate Validator 6 开始)。
反馈、问题、想法?
要取得联系,请使用通常的渠道
-
用户论坛(使用问题,一般反馈)
-
问题跟踪器(错误报告,功能请求)
-
邮件列表(与开发相关的讨论)
-
Jakarta Bean Validation 开发邮件列表(关于 Jakarta Bean Validation 规范的讨论)