TIL - 20260313

juni·2026년 3월 13일

TIL

목록 보기
291/316

0313 스프링 부트 프로젝트 (5/N): Spring Security와 JWT 인증


✅ 1. Spring Security: 애플리케이션 보안의 표준

  • Spring Security는 Spring 기반 애플리케이션의 인증(Authentication)인가(Authorization)를 담당하는 강력한 프레임워크입니다. 서블릿 필터(Filter) 체인을 기반으로 동작하여, 요청이 컨트롤러에 도달하기 전에 다양한 보안 검사를 수행합니다.

➕ 의존성 추가 (build.gradle)

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-security'
}
  • 이 의존성을 추가하는 것만으로, Spring Boot는 모든 엔드포인트에 대해 기본적으로 인증을 요구하는 보안 설정을 자동 적용합니다.

✅ 2. 보안 설정 구성 (SecurityConfig)

  • 애플리케이션의 보안 규칙(URL별 접근 제어, 로그인 방식, 인증 방식 등)을 Java 설정 코드로 정의합니다.

➕ 주요 설정

  1. @Configuration & @EnableWebSecurity: 이 클래스가 보안 설정 클래스임을 Spring에 알립니다.
  2. SecurityFilterChain Bean: HTTP 요청에 대한 보안을 처리하는 필터 체인을 정의합니다.
    • authorizeHttpRequests: URL 경로별로 접근 권한을 설정합니다.
      • requestMatchers(...).permitAll(): 특정 경로는 인증 없이 모두 접근 허용. (e.g., 회원가입, 로그인 API)
      • anyRequest().authenticated(): 그 외 모든 요청은 반드시 인증된 사용자만 접근 허용.
    • csrf(AbstractHttpConfigurer::disable): CSRF(Cross-Site Request Forgery) 보호 기능을 비활성화합니다. (Stateless한 JWT 방식에서는 일반적으로 비활성화)
    • sessionManagement: 세션 관리 정책을 설정합니다. JWT를 사용할 것이므로, 세션을 생성하지 않는 STATELESS로 설정합니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/api/auth/**").permitAll() // 회원가입/로그인 API는 허용
                .anyRequest().authenticated()
            );
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 비밀번호 암호화를 위한 BCryptPasswordEncoder
        return new BCryptPasswordEncoder();
    }
}

✅ 3. JWT (JSON Web Token) 기반의 Stateless 인증

  • JWT는 서버가 클라이언트의 상태를 저장하지 않는 Stateless(무상태) 인증 방식입니다. 인증 성공 시 서버는 사용자 정보를 담은 암호화된 토큰을 발급하고, 클라이언트는 이후 요청마다 이 토큰을 헤더에 담아 보내 인증을 증명합니다.

➕ JWT 관련 의존성 추가 (build.gradle)

dependencies {
    implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
}

➕ JWT 생성 및 검증 로직 (JwtTokenProvider)

  • JWT의 생성, 유효성 검증, 정보 추출을 담당하는 별도의 유틸리티 클래스를 만듭니다.
    • generateToken(): 사용자 정보를 받아 JWT를 생성합니다.
    • validateToken(): 토큰의 유효성(서명, 만료 시간 등)을 검증합니다.
    • getAuthentication(): 토큰에서 사용자 정보를 추출하여 Spring Security의 Authentication 객체를 생성합니다.

✅ 4. JWT 인증 필터 (JwtAuthenticationFilter)

  • 클라이언트의 모든 요청을 가로채, HTTP 헤더에서 JWT를 확인하고 인증을 처리하는 커스텀 필터를 구현합니다.

➕ 필터 동작 흐름

  1. 요청의 Authorization 헤더에서 Bearer 토큰을 추출합니다.
  2. JwtTokenProvider를 사용하여 토큰의 유효성을 검증합니다.
  3. 토큰이 유효하면, JwtTokenProvider를 통해 Authentication 객체를 생성합니다.
  4. 생성된 Authentication 객체를 SecurityContextHolder에 저장합니다.
    • SecurityContextHolder: Spring Security가 현재 인증된 사용자의 정보를 저장하는 공간. 여기에 인증 정보가 저장되면, 해당 요청은 "인증된" 것으로 간주됩니다.
  5. 다음 필터로 요청을 전달합니다.
  • 이 커스텀 필터를 SecurityConfig에서 UsernamePasswordAuthenticationFilter 앞에 추가하여, 모든 비즈니스 로직보다 먼저 JWT 인증이 수행되도록 설정합니다.
// SecurityConfig에 필터 추가
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class)

✅ 5. 회원가입 및 로그인 API 구현

  1. 회원가입 API:

    • PasswordEncoder를 사용하여 사용자의 비밀번호를 암호화하여 DB에 저장합니다.
  2. 로그인 API:

    • 사용자가 제출한 비밀번호와 DB에 저장된 암호화된 비밀번호를 passwordEncoder.matches()를 통해 비교합니다.
    • 인증에 성공하면, JwtTokenProvider를 사용하여 Access TokenRefresh Token을 생성하여 클라이언트에게 반환합니다.

📌 요약

  • Spring Security는 의존성 추가만으로 기본적인 보안을 활성화하며, SecurityFilterChain Bean을 통해 세부적인 보안 규칙을 Java 코드로 설정합니다.
  • JWT는 서버의 상태 저장이 필요 없는 Stateless 인증 방식으로, 서버 확장성에 유리합니다.
  • JWT 인증을 구현하기 위해, 토큰의 생성/검증을 담당하는 JwtTokenProvider와, 모든 요청을 가로채 토큰을 검사하는 JwtAuthenticationFilter를 구현해야 합니다.
  • 인증이 완료된 사용자 정보는 SecurityContextHolder에 저장되어, 애플리케이션 전반에서 현재 로그인된 사용자를 식별하는 데 사용됩니다.

0개의 댓글