코드스테이츠_국비교육/[Section4]

66.01_[Spring Security]JWT_인증 기능 구현_22.11.24

생각없이 해도 생각보다 좋다. 2022. 11. 24. 23:47

===============================
JWT 자격 증명을 위한 로그인 인증 구현
===============================
1. SecurtyConfiguration 추가
: Spring Security 인증/보안 기능 추가

1.1. SecurityFilterChain 메서드
>HttpSecurity
-headers
-csrf
-cors
-formLogin
-httpBasic
-authorizeHttpRequests
-and
-build

1.2. PasswordEncoder

1.3. CorsConfigurationSource

===============================
2. 회원 가입 로직 수정
: Spring Security 적용

2.1. MemberDto.Post 수정
>password 필드 추가

2.2. Member(Entity) 수정
>password 필드 추가

2.3. MemberService 수정
>DI
-PasswordEncoder 적용
-AuthorityUtils 적용, Custom
>createMember
-암호화 적용(PasswordEncoder)

//1,2 는 사전 작업
===============================
3. JWT 자격 증명을 위한 로그인 인증 구현
: 핵심은 Username(이메일)과 Password를 유저에게 받고, 이를 통해 로그인 인증에 성공하면 성공한 유저에게는 JWT를 생성 및 발급해주는 것
//대략적인 모식도를 이전에 Spring Security 인증 처리 컴포넌트 흐름과 매칭하여 파악하면 편함.
//그림 그리자.

3.1. Custom UserDetailsService 구현
>필요 기능
: 사용자의 크리덴셜을 DB에서 조회하는 기능
: 사용자의 크리덴셜을 포함하면서 인증되지 않은 Authentication을 기반으로 UserDetails 객체 생성
: UserDetails 객체를 AuthenticationManager에게 전달.
>구성
-DB사용; repository DI
-권한부여유틸사용; authorityUtils DI(Custom)
-크리덴셜 정보를 포함한 Userdetails 를 생성 및 반환하는 메서드
: 인증되지 않은 Authentication 중 특수 필드(예. username)를 이용해서 DB에서 원하는 user를 찾아 UserDetails 객체를 생성하여 반환(load)하는 메서드
-UserDetails를 custom 한 클래스 구현
: Member 상속
: UserDetails(인터페이스) 구현
: 상속한 클래스(Member)의 정보를 기반으로 크리덴셜을 포함한 UserDetails를 생성하는 생성자 구현
: UserDetails 메서드 구현

3.2. LoginDto 구현
: 클라이언트가 전송하는 username/password 정보를 역직렬화하는 DTO 클래스
: 즉, 자바 코드내에서 사용할 수 있게 만듬.

3.3. JwtTokenizer 구현
>필요 기능
: 로그인 인증 성공 시, JWT 생성 및 발급
: 전달된 JWT를 검증하는 역할
>구성
- 임시 secretKet와 각각의 토큰에 대한 임시 유효기간 필드 (학습을 위해 필요한 부분)
- SecretKey Enconding 메서드(Base64, String to String)
: SecretKey는 Plain Text로 사용 못함. 
: 내부에서 사용할 때, default로 인코딩한 상태로 사용하기 위한 메서드
- Key 객체 생성 메서드(HAMC, String to Key)
: 인코딩되어 있는 키를 인자로 받아 디코딩하고, 이를 HMAC과 같은 알고리즘으로 암호화하는 메서드
: Signature 생성할 때 설정할 Key 를 만들어주는 메서드
: 토큰 생성 메서드 내부에서 호출될 예정
- AccessToken 생성 메서드
: claims, subject, expiration, encodedSecreyKey를 인자로 받고, 이를 바탕으로 AccessToken 을 생성 및 반환하는 메서드(Jwts 사용)
- RefreshToken 생성 메서드
- subject, expiration, encodedSecreyKey를 인자로 받고, 이를 바탕으로 RefreshToken 을 생성 및 반환하는 메서드(Jwts 사용)
- 토큰에서 claims를 파싱하는 메서드
: 해당 메서드의 목적은 Token에서 claims(유저 정보)를 추출하는 것.
: signature을 암호화할 때 설정했던 Key 객체가 맞는지 검증하고, 검증이 완료되면 claims를 파싱하여 반환(반환형 Jws<Claims>)
- 토큰을 검증하는 메서드
: 토큰에 위변조가 없는지 검증
: claims 파싱 메서드와 똑같지만 void로 구현.
- 토큰의 만료 일시(expriation)을 설정하는 메서드
: Calender 클래스와 Date 클래스를 이용

3.4. Custom Security Filter 구현
: 로그인 인증 요청을 처리하는 Security Filter 구현
: UsernamePasswordAuthenticationFilter 을 구현하여 JWT 을 위해 쓰이는 필터
: 클라이언트가 서버로 보내는 로그인 인증 요청을 가장 먼저 받는 위치.
>필요 기능
: username, password를 받아 AuthenticationManager에게 전달하는 기능
: 생성된 JWT를 응답으로 전달하는 기능
>구성
-Manager에게 정보 전달 : AuthenticationManager DI
-JWT 생성 및 전달 : JwtTokenizer DI
-attempAuthentication 메서드 구현
: UsernamePasswordAuthenticationFilter의 메서드
: 인증 처리 위임이 목적
: 인증되지 않은 Authentication 을 생성하고, 이를 AuthenticationManager에게 전달(반환)하는 메서드
: JSON(requust)의 역직렬화 필요
-successfulAuthentiction 메서드 구현
: UsernamePasswordAuthenticationFilter의 메서드
: 로그인 인증을 성공적으로 마쳤을 경우 호출되는 메서드
: 인증된 Authentication 을 기반으로 토큰을 생성하고 response의 header에 정보를 표기함.
: 토큰을 생성하기 위해 Tokenizer 사용하여 토큰을 생성하고 반환하는 메서드를 사용
-delegateAccessToken/delegateRefreshToken
: Tokenizer를 통해 실제로 토큰을 생성하는 메서드
: successfulAuthentication에서 호출되어 호출된 내분에서 토큰을 생성하는 기능을 담당.
: Member(Entity)를 기반으로 토큰 구성요소 생성

3.5. SecurityConfiguration에 Custom Filter 의 사용 설정 추가
-CustomFilterConfigurer 내부에 DI를 하기 위한 JwtTokenizer DI
-filterChain 에 CustomFilterConfigurer을 적용하는 메서드 체인 추가
-CustomFilterConfigurer class 구현
: Custom Security Filter인 JwtAuthenticationFilter를 적용하기 위한 Configuration

===============================
추가 기능; 로그인 인증 성공 및 실패에 따른 추가 처리 기능
===============================

1. Custom AuthenticationSuccessHandler 클래스 구현
-onAuthenticationSuccess 메서드 구현
: 해당 메서드를 구현하면서 인증 성공 후 추가로 처리할 작업을 작성할 수 있음.

2. Custom AuthenticationFailureHandler 클래스 구현
-onAuthenticationFailure 메서드 구현
-sendErrorResponse 메서드 구현
: onAuthenticationFailure 메서드에서 호출되어 출력 스트림에 Error 정보를 담는 메서드

3. SecurityConfiguration 수정
-JwtAuthenticationFilter 등록
: AuthenticationSuccessHandler와 AuthenticationFailureHandler를 사용하려면 JwtAuthenticationFilter에 등록해야한다.

//지금까지 한 작업은 사용을 위한 설정 작업.
//실제 사용을 하는 코드를 작성해야함. (메서드 호출하기)
4. JwtAuthenticationFilter 수정
: SuccessHandler와 FailureHandler를 JwtAuthenticationFilter내부에서 적절한 곳에 호출하는 코드를 작성한다.

===============================

대표적인 Filter로 UsernamePasswordAuthenticationFilter를 사용하여 JWT 로그인 인증 기능을 구현했지만, 사실 다른 Filter를 이용하거나 Controller에서 구현해도 되긴함.

상황에 맞게 적절히 사용할 것.