스프링

server side validation

 

목차

사용자가 입력한 값에 대한 유효성을 서버에서 체크하는 것 ( 그동안은 client에서 했는데, 이것은 보안측면에서 봤을 때 좋지 않아)

이것 반드시 해야해.

  • User validation check 추가 및 error message 처리
    • validation library 추가
    • validation annotation 처리
    • 에러 메시지 처리
  • validation error를 jsp에 보여주기
  • 단위 테스트로 validation check 자동화하기

User validation check 추가 및 error message 처리

  1. spring mvc validation example annotation을 구글에 검색해서 링크 참고.
  2. 링크 잘 읽어보시고, 하단의 코드 pom.xml에 추가
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.1.0.Final</version>
        </dependency>
* 위에서의 링크를 잘 읽어보면, 어떤 형태로 validation check를 할 수 있는지 써있어. 
  1. User class를 하단의 코드처럼 바꿈
        @NotNull @Min(4) @Max(12)
	private String userId;
	@NotNull @Min(4) @Max(12)
	private String password;
	@NotNull
	private String name;
	@Email
	private String email;

  1. UserController class를 하단의 코드처럼 바꿈
	public String create(@Valid User user, BindingResult bindingResult){
		logger.debug("User : {}", user);
		if ( bindingResult.hasErrors()) {
			logger.debug("binding Result has error!");
			List<ObjectError> errors = bindingResult.getAllErrors();
			for (ObjectError error : errors) {
				logger.debug("error : {}, {}", error.getCode(), error.getDefaultMessage());
			}
			//validation에서 에러가 뜨면 다시 입력화면으로 넘어갈겡 
			return "users/form";
		}
		userDao.create(user);
		logger.debug("Database: {}", userDao.findById(user.getUserId()));
		//에러가 에러가 없을 때는 다시 입력화면으로 넘어갈 것이 아니라, 메인으로 넘어가는게 좋으니까. 
		return "redirect:/";
	}
  1. 구글에서 java validation annotation list로 검색하여 링크로 들어가서, 어떤 annotation을 쓸 수 있는지, custom validation check는 어떻게 할건지 등등 알아봐
    • 또 다른 링크로는 튜토리얼 링크가 있어. 예시까지 아주 친절하니까 잘 보렴

*** User에서 추가한 코드를 약간 수정

        @NotEmpty @Size(min=4, max=12)
	private String userId;
	@NotEmpty @Size(min=4, max=12)
	private String password;
	@NotEmpty
	private String name;
	@Email
	private String email;
  • 이유는

validation error를 jsp에 보여주기

  • error 발생시 사용자에게 발생한 error message를 보여주도록 처리
  1. src/main/resources에 file을 추가 (messages.properties)
  2. 하단의 코드 추가
Size.user.userId = User {0} should be between {2} and {1} characters long
NotEmpty.user.userId = User {0} is required

Size.user.password = User password {0} should be between {2} and {1} characters long
NotEmpty.user.password = User {0} is required
NotEmpty.user.name = User {0} is required

* 뜻 
    * Size(유효성체크한 annotation이름).user(클래스 이름, 대문자 아님!!! 주의!!).userId(필드이름) = User {0} should be between {2} and {1} characters long
  1. rbwiki-servlet.xml에 하단의 코드 추가
<bean id ="messageSource" class = "org.springframework.context.support.ResourceBundleMessageSource" p:basename="messages" 
p:defaultEncoding="UTF-8" 
/> 
* [[spring localization example | http://www.journaldev.com/2610/spring-mvc-internationalization-i18n-and-localization-l10n-example]] 을 참고하면 설정하는 방법이 나와있음. 
* 한가지, classpath:는 추가하지 않는 것이 다름. 그렇게 하면 파일을 못찾아서 그냥 src/main/resources 하단에 놓고 쓰기로.
  1. 이제 이 error message를 사용자한테 보여줘야하니까, form.jsp의 각 필드마다 하단의 코드를 추가
<form:errors path="userId" cssClass="error" />

] 5. UTF-8을 추가함으로써 messages.properties 파일에 한글이 추가가 되지만 보기 불편하게 나온다. 이를 해결하기 위해 plugin설치

* help > eclipse marketplace > properties editor 검색 후 install > 전부 체크후 confirm > accept > 자동 재시작
  1. 이제 messages.properties에 가서 한글로 치면 정상적으로 보기 편하게 나온다.

  2. 추가적으로 spring localization example 에서 다국어 지원에 대한 설정도 할 수 있도록 나와있다.

    • messages.properties는 default 언어로 하고, messages_en.properties를 하면 영어, messages_fr.properties로 하면 프랑스어 등으로 설정할 수 있다고 나와있음.

단위 테스트로 validation check 자동화하기

  • java validation test는 hibernate라는 구현체를 사용
    • 첫번째 목차에서 dependency 이미 추가
    • 함께 추가했던 javax.validation은 삭제해도 됨.
      • dependency hierarchy에 확인해보면, hibernate-validator가 추가되면 자동으로 javax.validation도 추가되게 되어있음
  • hibernate validator test를 참고
  1. User.java에서 eclipse 상단의 c+모양 아이콘 클릭해서 Junit Test Case 클릭 > package를 src/test/java로 바꿔줌
  2. 하단의 코드 추가
	private static Validator validator; 
	
	@BeforeClass
	public static void setUp() {
		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
		validator = factory.getValidator();
	}
* @beforeclass의 역할
    * @before의 경우, 매 단위테스트마다 실행되는 것이고, @beforeclass는 테스트 통틀어 한번만 실행되는거야. 
    * 그에 대비되는 개념으로 @afterclass와 @after가 있어
  1. UserId 값이 empty일 때 제대로 처리되는지 확인하는 코드
        @Test
	public void userIdWhenIsEmpty() {
		//사용자 데이터를 하나 추가하고
		User user = new User("", "password", "name","111@111.com");
		//유효성체크를 하자
		Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);
		// validation이 맞지 않는 것이 2개인지 체크해라. (size를 지키지 않은 것, notempty를 지키지 않은 것) 
		assertThat(constraintViolations.size(), is(2));
	}
* 뜻이 뭘까..뭐니?
    * 에러 발생 
        * 위에서 제공한 링크의 문서를 참고하여 아래의 코드를 추가함으로써 해결
                <dependency>
			<groupId>javax.el</groupId>
			<artifactId>javax.el-api</artifactId>
			<version>2.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.web</groupId>
			<artifactId>javax.el</artifactId>
			<version>2.2.4</version>
		</dependency>

* 테스트 성공 후 , 하단의 코드를 추가하여 validation violated된 부분을 에러 메세지로 확인할 수 있도록 함 .
for (ConstraintViolation<User> constraintViolation : constraintViolations) {
    logger.debug("validation error message: {}", constraintViolation.getMessage());
}
    * 그런데, 에러 메세지가 messages.properties의 내용이 아니다. 
        * testclass에서 사용중인 에러 메시지는 validation jar파일에서 기본으로 제공하고 있는 한글용 에러 메시지

 

 

 

 

 

	@RequestMapping(value="", method=RequestMethod.POST)
	public String create(@Valid User user, BindingResult bindingResult ){
		logger.debug("User : {} " , user);
		if(bindingResult.hasErrors()){
			logger.debug("Binding Result has error!");
			List<ObjectError> errors=bindingResult.getAllErrors();
			for(ObjectError error : errors){
				logger.debug("error : {}, {}", error.getCode(), error.getDefaultMessage());
			}
			
			return "users/form";
		}
		userDao.create(user);
		logger.debug("Database : {} " , userDao.findById(user.getUserId()));
		return "redirect:/";
	}
	

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  머나먼나라

효도하고 순한 사람은 또한 효도하고 순한 아들을 낳으며, 오역(불교의 지옥에 갈만한 큰 죄)한 사람은 또한 오역한 아들을 낳는다. 믿지 못한다면, 저 차마 끝의 낙수(落水)를 보라. 방울방울 떨어져 내림이 어긋남이 없다. -명심보감

댓글 ( 4)

댓글 남기기

작성