[Spring/심화] Bean, 인증/인가, JWT, Spring Security, Validation

JM·어제

이번 주의 핵심 흐름

Bean
 ↓
인증(Authentication) / 인가(Authorization)
 ↓
Cookie / Session
 ↓
JWT
 ↓
Filter
 ↓
Spring Security
 ↓
Validation

1. Bean 수동 등록

Bean

Spring IoC Container가 생성하고 관리하는 객체

일반적으로 @Component, @Service, @Repository, @Controller 등을 사용하여 자동 등록됨

Bean 수동 등록

@Configuration + @Bean 사용

@Configuration
public class PasswordConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

수동 등록이 필요한 경우

비즈니스 로직보다는 기술적인 기능이나 공통 관심사를 처리하는 객체에 적합하다.

  • PasswordEncoder
  • 공통 설정
  • 로깅 등 기술 지원 Bean

핵심

@Configuration
    ↓
@Bean
    ↓
Spring IoC Container에 Bean 등록

2. 같은 타입의 Bean이 여러 개일 때

같은 타입의 Bean이 여러 개 존재하면 @Autowired만으로 어떤 Bean을 주입해야 하는지 판단하기 어려움

@Primary

여러 Bean 중 기본적으로 주입할 Bean 지정

@Primary
@Component
public class Chicken implements Food {
}

@Qualifier

특정 Bean을 명시적으로 지정.

@Qualifier("pizza")
Food food;

우선순위

@Qualifier
    ↓
@Primary

같은 타입의 Bean이 여러 개라면

  • 기본적으로 사용할 Bean → @Primary
  • 특정 상황에서 사용할 Bean → @Qualifier

인증과 인가

3. 인증(Authentication)과 인가(Authorization)

인증(Authentication)

사용자가 실제로 누구인지 확인하는 과정

예시

  • 로그인
  • 비밀번호 확인
  • 지문 인증

인가(Authorization)

인증된 사용자가 특정 리소스에 접근할 권한이 있는지 확인하는 과정

예시

  • 일반 사용자 → 일반 페이지 접근 가능
  • 관리자 → 관리자 페이지 접근 가능

핵심 차이

인증
"너 누구야?"

        ↓

인가
"너 이거 볼 수 있어?"

4. HTTP의 특징

비연결성(Connectionless)

HTTP 통신은 기본적으로 요청과 응답이 끝나면 연결을 종료하는 방식

→ 서버의 리소스 절약

무상태(Stateless)

서버가 이전 요청의 상태를 저장하지 않는 특성

즉, 서버는 현재 요청만으로 사용자의 이전 상태를 알 수 없다.

문제점

로그인한 사용자가 다음 요청을 보냈을 때

"이 사용자가 로그인한 사용자인가?"

를 서버가 알 수 있어야 함.

→ Cookie / Session / JWT 등의 인증 방식 사용


Cookie와 Session

클라이언트에 저장되는 작은 데이터

브라우저에 저장되며 서버와 통신할 때 함께 전달 가능하다.

  • Name
  • Value
  • Domain
  • Path
  • Expires

특징

  • 클라이언트 저장
  • 만료 시간 설정 가능
  • 서버에 저장하지 않아도 됨

6. Session

서버에서 클라이언트의 상태를 유지하기 위한 저장 방식

서버가 사용자의 정보를 저장하고, 클라이언트에는 Session ID를 전달

동작 과정

Client
 ↓
Login 요청
 ↓
Server
 ↓
Session 생성
 ↓
Session ID 발급
 ↓
Cookie에 Session ID 저장
 ↓
이후 요청마다 Session ID 전달
 ↓
Server가 Session 확인
구분CookieSession
저장 위치ClientServer
주요 역할데이터 저장사용자 상태 유지
대표 사용팝업 설정 등로그인
식별 정보Cookie ValueSession ID

JWT

7. JWT란?

JSON Web Token

인증에 필요한 정보를 토큰에 담아 사용하는 인증 방식

Cookie-Session 방식과 달리 로그인 상태를 서버에 저장하지 않고 토큰 자체에 정보를 포함할 수 있다

JWT 인증 흐름

로그인 요청
   ↓
ID / Password 확인
   ↓
JWT 생성
   ↓
Client에 JWT 전달
   ↓
Client가 JWT 저장
   ↓
이후 요청마다 JWT 전달
   ↓
Server에서 JWT 검증
   ↓
인증 완료

8. JWT 구조

JWT는 다음 세 부분으로 구성됨

Header.Payload.Signature

토큰의 타입과 암호화 알고리즘 등의 정보

Payload

사용자 정보 등의 Claim 저장

{
  "sub": "username",
  "auth": "ROLE_USER"
}

Signature

Header + Payload를 Secret Key로 서명한 값

토큰이 변조되었는지 검증하는 데 사용한다.

중요한 점

JWT의 Payload는 암호화되어 있는 것이 아님.

따라서 누구나 Payload를 확인할 수 있다.

Secret Key가 필요한 부분은 Signature 검증 및 위변조 방지.

→ 비밀번호와 같은 민감한 정보를 Payload에 저장하면 안 된다.


9. JWT의 장단점

장점

  • 서버에 로그인 상태를 저장하지 않아도 됨
  • 서버 확장에 유리
  • 여러 서버 환경에서 사용하기 편리
  • Client와 Server의 도메인이 다른 환경에서도 활용 가능

단점

  • 구현 복잡도 증가
  • Token 크기가 커지면 네트워크 비용 증가
  • 발급된 Token을 일부만 즉시 만료시키기 어려움
  • Secret Key 유출 시 보안 문제 발생

10. JWT 주요 처리

JWT를 사용할 때 필요한 기능

  • JWT 생성
  • Cookie에 JWT 저장
  • JWT 추출
  • Bearer 제거
  • JWT 검증
  • JWT에서 사용자 정보 추출

JWT 검증

JWT
 ↓
Signature 검증
 ↓
만료 여부 확인
 ↓
정상 JWT인지 확인

사용자 관리

11. 비밀번호 암호화

회원가입 시 비밀번호를 평문으로 DB에 저장하면 안 됨.

평문 비밀번호
      ↓
암호화
      ↓
암호문
      ↓
DB 저장

단방향 암호화

암호화는 가능하지만 복호화가 불가능한 방식

평문 → 암호문
      ↑
      X
복호화 불가능

비밀번호 저장에는 일반적으로 단방향 해시 방식 사용한다.

PasswordEncoder

Spring Security에서 제공하는 비밀번호 암호화 기능

passwordEncoder.encode(password);

로그인 시에는

passwordEncoder.matches(
    입력된 비밀번호,
    DB에 저장된 암호화된 비밀번호
);

형태로 비교.


12. 사용자 권한

사용자 역할은 Enum으로 관리 가능하다.

USER
ADMIN

Spring Security에서 권한을 사용할 때는 일반적으로 ROLE_ 접두사 사용한다.

ROLE_USER
ROLE_ADMIN

Filter

13. Filter

Client의 요청과 Server의 응답 사이에서 공통적인 작업을 처리하는 역할

주로 다음과 같은 작업에 사용한다.

  • 로깅
  • 인증
  • 인가
  • 보안 처리

장점

인증이나 로깅 같은 공통 기능을 Controller의 비즈니스 로직과 분리 가능.


14. Filter Chain

Filter는 하나만 존재하는 것이 아니라 여러 Filter가 Chain 형태로 연결될 수 있다.

Request
 ↓
Filter 1
 ↓
Filter 2
 ↓
Filter 3
 ↓
Controller
 ↓
Response

chain.doFilter()

현재 Filter의 처리가 끝난 후 다음 Filter로 요청 전달한다.


Spring Security

15. Spring Security

Spring 애플리케이션의 인증과 인가를 처리하기 위한 보안 프레임워크

직접 Filter를 구현하는 것보다 인증/인가 기능을 편리하게 구성할 수 있다.

주요 기능

  • 인증
  • 인가
  • 비밀번호 암호화
  • 권한 관리
  • Security Filter Chain

16. Security Filter Chain

Spring Security는 여러 Filter를 연결하여 인증과 인가를 처리한다.

Client
 ↓
Spring Security Filter Chain
 ↓
인증 / 인가
 ↓
Controller

인증이 실패하면 Controller까지 요청이 전달되지 않음.


17. SecurityContextHolder

현재 인증된 사용자의 정보를 저장하는 공간

SecurityContextHolder
        ↓
SecurityContext
        ↓
Authentication
        ↓
UserDetails

Authentication

현재 인증된 사용자를 나타내는 객체

주요 정보

  • Principal → 사용자 식별 정보
  • Credentials → 인증에 사용된 정보
  • Authorities → 사용자 권한

18. UserDetails와 UserDetailsService

UserDetails

Spring Security가 사용하는 인증된 사용자 정보 객체.

사용자 정보와 권한을 Spring Security에서 사용할 수 있는 형태로 제공한다.

UserDetailsService

사용자 이름을 기반으로 DB에서 사용자를 조회하고 UserDetails로 변환하는 역할

username
   ↓
UserDetailsService
   ↓
DB에서 User 조회
   ↓
UserDetails 생성
   ↓
Authentication

@AuthenticationPrincipal

Controller에서 현재 인증된 UserDetails를 쉽게 가져올 수 있음

@GetMapping("/products")
public String getProducts(
        @AuthenticationPrincipal UserDetailsImpl userDetails
) {
    ...
}

Spring Security + JWT

19. JWT Authentication Filter

로그인 요청을 처리하고 JWT를 생성하는 Filter

역할

로그인 요청
 ↓
username / password 확인
 ↓
AuthenticationManager
 ↓
인증 성공
 ↓
JWT 생성
 ↓
Cookie에 JWT 저장

20. JWT Authorization Filter

API 요청에 포함된 JWT를 검증하고 인증 정보를 설정하는 Filter

역할

API 요청
 ↓
JWT 추출
 ↓
JWT 검증
 ↓
사용자 정보 추출
 ↓
Authentication 생성
 ↓
SecurityContextHolder에 저장
 ↓
Controller

Authentication Filter와 Authorization Filter

Filter역할
JwtAuthenticationFilter로그인 인증 및 JWT 생성
JwtAuthorizationFilterJWT 검증 및 API 접근 인가

21. Stateless

JWT 방식에서는 서버에 Session을 저장하지 않고 JWT를 사용하여 인증 상태를 유지

.sessionCreationPolicy(
    SessionCreationPolicy.STATELESS
)

Session 방식

Client
 ↓
Session ID
 ↓
Server Session

JWT 방식

Client
 ↓
JWT
 ↓
Server에서 검증

권한 관리

22. Authority

Spring Security에서 사용자의 권한을 GrantedAuthority 형태로 관리한다.

ROLE_USER
ROLE_ADMIN

SimpleGrantedAuthority

new SimpleGrantedAuthority("ROLE_ADMIN");

사용자의 권한 정보를 Spring Security가 이해할 수 있는 형태로 변환한다.


23. @Secured

Controller의 특정 API에 필요한 권한을 지정할 수 있다.

@Secured(UserRoleEnum.Authority.ADMIN)
@GetMapping("/products/secured")
public String getProductsByAdmin() {
    ...
}

결과

ROLE_ADMIN → 접근 가능
ROLE_USER  → 접근 불가

즉, 인증(Authentication)과 인가(Authorization)를 분리해서 생각하는 것이 중요하다.


Validation

24. Validation

Client가 전달한 데이터가 올바른 형식인지 검증하는 과정

잘못된 데이터가 Service나 DB까지 전달되지 않도록 요청 단계에서 검증한다.

주요 Annotation

Annotation의미
@NotNullnull 불가
@NotEmptynull, 빈 문자열 불가
@NotBlanknull, 빈 문자열, 공백 불가
@Size문자열 길이 검증
@Max최대값
@Min최소값
@Positive양수
@Negative음수
@Email이메일 형식
@Pattern정규식 검증

25. @Valid

DTO에 설정한 Validation 조건을 실제로 검사하도록 하는 역할

@PostMapping("/validation")
public ProductRequestDto testValid(
        @RequestBody @Valid ProductRequestDto requestDto
) {
    return requestDto;
}

동작 흐름

Client Request
      ↓
DTO
      ↓
@Valid
      ↓
Validation
      ↓
정상 → Controller 처리
오류 → Validation Exception

26. BindingResult

Validation 과정에서 발생한 오류 정보를 확인할 때 사용한다.

public String signup(
        @Valid SignupRequestDto requestDto,
        BindingResult bindingResult
) {
    ...
}

주요 정보

FieldError를 통해

  • 어떤 필드에서 오류가 발생했는지
  • 어떤 검증 조건을 위반했는지

확인 가능.


27. 이번 주 핵심 키워드

Bean

  • Spring이 관리하는 객체
  • @Component
  • @Bean
  • @Configuration
  • @Primary
  • @Qualifier

인증 / 인가

  • Authentication → 사용자 확인
  • Authorization → 접근 권한 확인
  • Stateless
  • Connectionless
  • Cookie → Client 저장
  • Session → Server 저장
  • Session ID

JWT

  • Header
  • Payload
  • Signature
  • Claim
  • Secret Key
  • Bearer
  • Token 검증
  • Stateless 인증

Spring Security

  • Security Filter Chain
  • Authentication
  • SecurityContext
  • SecurityContextHolder
  • UserDetails
  • UserDetailsService
  • AuthenticationManager
  • @AuthenticationPrincipal
  • Authority
  • @Secured

Filter

  • Request / Response 공통 처리
  • Filter Chain
  • chain.doFilter()
  • Logging
  • Authentication
  • Authorization

Validation

  • @Valid
  • @NotBlank
  • @Email
  • @Size
  • @Positive
  • @Negative
  • BindingResult
  • FieldError

마무리

Spring에서 인증과 인가를 처리하는 전체 흐름을 이해하는게 제일 힘들다...

흐름 기억하기!!

회원가입
 ↓
비밀번호 암호화
 ↓
DB 저장
 ↓
로그인
 ↓
Authentication
 ↓
JWT 생성
 ↓
Client에 전달
 ↓
API 요청
 ↓
JWT 검증
 ↓
SecurityContext에 Authentication 저장
 ↓
Controller 접근
 ↓
권한 확인

0개의 댓글