signup 페이지의 폼 입력결과를 signupDto로 받고.
이를 Builder를 활용해 User객체에 대입한 후.
JPA로 구현한 UserRepository를 활용해 UserService에서 User객체를 DB에 저장하였다.
그 후 Validation 조건을 주었는데, @Valid를 사용하고 BindingResult에 값이 존재할 경우 errorMap에 저장하게 하였다.
또한 BindingResult에 값이 있으면 CustomValidationException을 던지고.
ControllerExceptionHandler에서 이를 처리하도록 해주었다.
ControllerExceptionHandler에서는 브라우저에게 CMRespDto 객체를 반환하거나, JS 코드를 반환하여 경고를 출력해줄 수 있다.
즉 검증 처리를 완료한 회원가입을 구현하였다.
이제 로그인을 구현해보자.
signin.jsp 에서 login결과를 /auth/signin 으로 POST 전송하도록 변경한다.
로그인은 ID와 PW 조합이 DB에 존재하는지 확인하는 작업이므로 기능상 GET에 더 가깝다.
하지만 ID와 PW 넘겨줄 때 body에 담아 숨겨 전송하기 위해 POST로 전송한다.
SecurityConfig 에서 loginProcessingUrl 을 추가한다.
회원가입은 Controller를 우리가 직접만들어 구현했지만 로그인은 SpringSecurity 가 알아서 처리한다.
Springsecurity는 인증되지 않은 사용자가 페이지 요청시 /auth/signin 를 넘겨주고.
Post 방식으로 /auth/signin 에 요청시 login 과정을 진행한다.
0) 시큐리티에 .loginProcessingURL("/auth/signin")을 추가한다. 추가하면 UserDetailService를 스프링빈으로 등록하게 된다.
1) 서버 시큐리티는 /auth/signin으로 POST요청이 들어오는지 주시하고 있다.
2) 클라이언트가 /auth/signin 으로 POST 요청을 하게되면 username과 password를 넘겨줄 것이다.
3) 이 때 빈으로 등록되었던 UserDetailService가 로그인처리를 진행하게 된다.
UserDetailService를 상속받는 PrincipalDetailsService를 생성하고 빈으로 등록하자.
그러면 스프링 컨테이너는 빈에 등록된 부모 클래스 UserDetailService를 PrincipalDetailService로 대체하고, 로그인 처리를 자식 클래스에게 맡기게 된다.
이제 로그인 로직을 PrincipalDetailsService 의 loadUserByUsername 메서드 내에 정의하면 된다.
1) 로그인을 수행할 UserRepository를 의존성주입한다.
2) UserRepository에서 findByUsername 메서드를 생성한다. JPA는 save, findAll 같은 기본 메서드를 제공하나 컬럼명 검색은 제공하지 않는다. 이에 따라 query Method 에서 메서드를 생성해준다.
3) PrincipalDetailsService 메서드에서 User 를 찾고, 이를 UserDetails 형으로 반환해야한다. 따라서 User를 필드로 갖는 PrincipalDetails 형으로 반환하자. UserDetails 형으로 반환하기만 하면 스프링 시큐리티가 자동으로 로그인 세션을 만든다.
4) UserDetails 를 상속하는 PrincipalDetails 클래스이다. User를 멤버로 갖고, UserDetails 의 모든 메서드들을 오버라이딩 해준다. 권한을 반환하는 getAuthorities는 Collection 을 반환형으로 갖음에 유의한다.
로그인 시도시 성공하면 제대로 defaultSuccessUrl인 /으로 이동하는 것을 볼 수 있다.