티스토리 뷰

회원가입 구현
1. Controller에 PostMapping 설정
2. 회원가입 예외처리 설정
- 어떤 곳에서 발생한 오류인지 구분하기 위한 Enum ExceptionClass를 필드로 가지는 Constants 생성
public class Constants {
public enum ExceptionClass {
LOGIN_USERNAME("로그인 아이디"), LOGIN_PASSWORD("로그인 비밀번호"),
SIGNUP_USERNAME("회원 가입 아이디"), SIGNUP_PASSWORD("로그인 패스워드"), SIGNUP_PASSWORDCHECK("로그인 패스워드 확인");
private String exceptionClass;
ExceptionClass(String exceptionClass) {
this.exceptionClass = exceptionClass;
}
public String getExceptionClass() {
return exceptionClass;
}
@Override
public String toString() {
return getExceptionClass() + " 오류 발생. ";
}
}
}
- UserException 작성
public class UserException extends Exception{
private static final long serialVersionUID = 827419284719293L;
private Constants.ExceptionClass exceptionClass;
private HttpStatus httpStatus;
public UserException(Constants.ExceptionClass exceptionClass, HttpStatus httpStatus, String message) {
super(exceptionClass.toString() + message);
this.exceptionClass = exceptionClass;
this.httpStatus = httpStatus;
}
public Constants.ExceptionClass getExceptionClass(){
return exceptionClass;
}
public int getHttpStatusCode() {
return httpStatus.value();
}
public String getHttpStatusType() {
return httpStatus.getReasonPhrase();
}
public HttpStatus getHttpStatus() {
return httpStatus;
}
}
- UserExceptionHandler 작성
@RestControllerAdvice
public class UserExceptionHandler {
@ExceptionHandler(value = UserException.class)
public ResponseEntity<Map<String, String>> ExceptionHandler(UserException e) {
HttpHeaders responseHeaders = new HttpHeaders();
Map<String, String> map = new HashMap<>();
map.put("error type", e.getHttpStatusType());
map.put("code", Integer.toString(e.getHttpStatusCode()));
map.put("message", e.getMessage());
return new ResponseEntity<>(map, responseHeaders, e.getHttpStatus());
}
}
스프링 시큐리티
Sevlet이란?
웹 서버로 웹 페이지를 제공할 때 동적인 데이터를 제공하는 것을 도와주는 자바 소프트웨어 컴포넌트. 웹 클라이언트에게 요청을 받고 그에 대해 응답을 해준다.




로그인에 성공하게 되면 servlet container에서 session을 보내준다(Security ContextHolder). 이 세션은 Authentication 타입의 객체이며 User정보(UserDetails)를 담고있다. 결국 Security Session은 Authenticaion을 포함하고 Authentication 객체 안에는 UserDetails 객체가 존재한다. UserDetails에서 User 정보를 접근할 수 있다.
백앤드 프론트 연동
- 프론트는 백엔드 API 호출할 때 세션을 같이 넘겨야한다.
- 스프링 시큐리티는 프론트가 전송한 세션을 사용해서 인증을 검사한다.
- 백엔드 개발자는 세션인증 로직을 개발하지 않아도 된다.

Spring Security 의 DelegatingFilterProxy

Spring Security는 Spring 기반이며 Servlet Filter로 구현되어 있다. 하지만 서블릿 필터는 스프링 빈에 접근하지 못하도록 설정되어 있다. Filter가 Spring Bean을 이해하지 못하므로 사용하고자 하는 FilterChain들을 Servlet Container 기반의 필터 위에서 동작시키기 위해 DelegatingFilterProxy라는 클래스를 이용하여 Filter를 생성하는 작업을 Spring에게 위임한다.
FilterChainProxy

UsernamePasswordAuthenticationFilter

인메모리 사용자
애플리케이션이 실행 중인 동안만 존재하는 인메모리 사용자

UserDetails
public class UserDetailsImpl implements UserDetails {
private final Member member;
public UserDetailsImpl(Member member) {
this.member = member;
}
}
UserDetailsService
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private final MemberRepository memberRepository;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Member member = memberRepository.findByUsername(username).orElseThrow(
() -> new UsernameNotFoundException(username + "이 존재하지 않습니다")
);
return new UserDetailsImpl(member);
}
}
("/login") 요청이 오면 자동으로 UserDetailsService 타입으로 Ioc 되어있는 loadUserByUsername 메소드가 실행된다. 메소드 종료 후 리턴한 UserDetails이 Authentication 객체 내부에 들어가게 되고, Authentication은 Session 내부에 들어가게 된다.
Security Session(내부 Authentication(내부 UserDetails))
*주의

loadByUsername 매서드의 String username 매개변수는 반드시 ("/login")요청의 form태그 내 input 태그의 name명과 같아야한다.
로그인된 유저 조회
스프링 시큐리티는 spring mvc에서 로그인된 유저를 가져올 수 있도록하는 @AuthenticationPrincipal 어노테이션을 제공한다.
'항해99(7기) > 항해 5주차' 카테고리의 다른 글
[항해99 7D]미니프로젝트 4일차 (0) | 2022.06.15 |
---|---|
[항해99 7D]미니프로젝트 3일차 (0) | 2022.06.14 |
[항해99 7D] 미니프로젝트 2일차 (0) | 2022.06.12 |