Skip to content

Commit

Permalink
Create Bean-Validation-Expression-Language-Feature-Level.md
Browse files Browse the repository at this point in the history
  • Loading branch information
HomoEfficio authored Jul 31, 2021
1 parent aded37a commit 73be0bd
Showing 1 changed file with 98 additions and 0 deletions.
98 changes: 98 additions & 0 deletions Bean-Validation-Expression-Language-Feature-Level.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Bean Validation Expression Language Feature Level

https://www.baeldung.com/spring-validation-message-interpolation 에 보면 밸리데이션 메시지에 여러 값들을 주입해서 표시할 수 있다.

예를 들어 아래와 같이 밸리데이션 애노테이션을 지정하고,

```kotlin
@field: [
NotNull(message = "{err.client.field_required}")
NotBlank(message = "{err.client.field_required}")
Size(max = WorldVersion.MAX_NAME, message = "{err.client.illegal_size}")
]
val name: String,
```

ValidationMessages_ko_KR.properties 파일에 아래와 Expression Language 를 사용한 메시지를 지정해두면,

```
err.client.illegal_size=길이는 {min} 이상 {max} 이하여야 합니다. 입력값 길이: ${validatedValue.length()}
```

밸리데이션 실패시 아래은 메시지를 표시할 수 있다.

```
길이는 0 이상 100 이하여야 합니다. 입력값 길이: 101
```


## 문제

이게 스프링 부트 2.4 까지는 기본적인 메시지 설정만으로 동작했는데, 스프링 부트 2.5 에서는 아래와 같은 에러가 발생한다.

```
2021-07-31 18:15:07.495 ERROR 58182 --- [ main] o.h.v.i.e.m.ElTermResolver : HV000264: Unable to interpolate EL expression '${validatedValue.length()}' as it uses a disabled feature.
org.hibernate.validator.internal.engine.messageinterpolation.el.DisabledFeatureELException: Method execution is not supported when only enabling Expression Language bean property resolution.
at org.hibernate.validator.internal.engine.messageinterpolation.el.BeanPropertiesELResolver.invoke(BeanPropertiesELResolver.java:23) ~[hibernate-validator-6.2.0.Final.jar:6.2.0.Final]
at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:79) ~[tomcat-embed-el-9.0.46.jar:3.0.FR]
```


## 원인

`Method execution is not supported when only enabling Expression` 메시지가 영 구려서 뭔 뜻인지 금방 알기 어려웠는데,
알고 보니 메시지에서 `${validatedValue.length()}` 이렇게 `length()` 메서드 호출을 사용했는데, 기본 설정에서는 메서드 호출을 허용하지 않는다는 것이다.

찾아보니 Expression Language 에도 기능 지원 수준이 있었다. org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel 에 정의돼 있으며,
FeatureLevel 기본값은 BEAN_PROPERTIES 이고 이 수준에서는 메서드 호출을 사용할 수 없다.

메서드 호출을 사용하려면 BEAN_METHODS 로 설정해야 하는데, 주석에 보면 메서드 호출이 보안 약점으로 작용할 수도 있다고 한다.
그러니 웬만하면 메서드 호출을 허용하지 않는 게 좋겠고, 그래도 꼭 해야한다면 FeatureLevel 을 BEAN_METHODS 로 설정해줘야 한다.

어떻게?


## 설정

아직 @Incubation 이라 그런지 자료가 별로 없는데 메시지 설정 시 아래와 같이 추가해주면 된다.

```kotlin
import org.hibernate.validator.BaseHibernateValidatorConfiguration.CONSTRAINT_EXPRESSION_LANGUAGE_FEATURE_LEVEL
import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel
import org.springframework.context.MessageSource
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.support.ReloadableResourceBundleMessageSource
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean

@Configuration
class MessageConfig {
@Bean
fun messageSource(): MessageSource {
val messageSource = ReloadableResourceBundleMessageSource()
messageSource.setBasename("classpath:message/messages")
messageSource.setDefaultEncoding("UTF-8")
return messageSource
}

@Bean
fun getValidator(): LocalValidatorFactoryBean {
val bean = LocalValidatorFactoryBean()
bean.setValidationMessageSource(validationMessageSource())
// 여기!!
bean.validationPropertyMap[CONSTRAINT_EXPRESSION_LANGUAGE_FEATURE_LEVEL] = ExpressionLanguageFeatureLevel.BEAN_METHODS.name
return bean
}

private fun validationMessageSource(): MessageSource {
val messageSource = ReloadableResourceBundleMessageSource()
messageSource.setBasename("classpath:message/validation/ValidationMessages")
messageSource.setDefaultEncoding("UTF-8")
return messageSource
}
}


```

0 comments on commit 73be0bd

Please sign in to comment.