[TIL] 2025-03-12

Yuri·2025년 3월 12일

TIL

목록 보기
59/59
post-thumbnail

Spring Security

Spring Security 는 Spring 기반 애플리케이션의 인증(Authentication)과 인가(Authorization)를 담당하는 강력한 보안 프레임워크이다. 주로 웹 애플리케이션의 보안을 강화하는 데 사용되며, 다양한 인증 방식과 접근 제어 기능을 제공한다.

Spring Security 는 Filter 기반으로 Spring MVC 와 분리되어 관리 및 동작한다.

핵심 개념

🔑 인증 (Authentication)

→ 로그인 (ID/Password, OAuth, JWT)

  • 인증 과정
    사용자가 로그인 정보를 입력
    AuthenticationManager가 인증을 수행
    인증이 성공하면 SecurityContextHolder 에 인증 정보를 저장

🧑‍💼 인가 (Authorization)

→ 권한

  • 접근 방식
    URL 기반 보안
    메서드 기반 보안
    필터 기반 보안

Stateless-Spring-Security

Spring Security (2003) 👉 JWT 스펙 적용 (2018)

Spring Security 대부분의 스펙이 세션 방식을 기반으로 개발

Stateless 인증: 서버가 사용자 인증 상태를 저장하지 않고 JWT 토큰으로 인증을 처리

  • JwtAuthenticationToken
public class JwtAuthenticationToken extends AbstractAuthenticationToken {

    private final AuthUser authUser;

    public JwtAuthenticationToken(AuthUser authUser) {
        super(authUser.getAuthorities());
        this.authUser = authUser;
        setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return null; // session 스펙
    }

    @Override
    public Object getPrincipal() {
        return authUser;
    }
}
  • JwtAuthenticationFilter
	private void setAuthentication(Claims claims) {
        Long userId = Long.valueOf(claims.getSubject());
        String email = claims.get("email", String.class);
        UserRole userRole = UserRole.of(claims.get("userRole", String.class));

        AuthUser authUser = new AuthUser(userId, email, userRole);
        JwtAuthenticationToken authenticationToken = new JwtAuthenticationToken(authUser);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }
  • SecurityConfig
@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
    // @EnableMethodSecurity => @Secured 사용 가능
    private final JwtAuthenticationFilter jwtAuthenticationFilter;

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

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                ) // stateless 인증
                .addFilterBefore(jwtAuthenticationFilter, SecurityContextHolderAwareRequestFilter.class)
                .formLogin(AbstractHttpConfigurer::disable) // 폼로그인 비활성화
                .anonymous(AbstractHttpConfigurer::disable) // 익명사용자 권한 비활성화
                .httpBasic(AbstractHttpConfigurer::disable) // BasicAuthenticationFilter 비활성화
                .logout(AbstractHttpConfigurer::disable) // 로그아웃 비활성화 -> 클라이언트가 JWT 삭제
                .rememberMe(AbstractHttpConfigurer::disable) // RememberMeAuthenticationFilter 비활성화
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers(request -> request.getRequestURI().startsWith("/auth")).permitAll()
                        .requestMatchers("/test").hasAuthority(UserRole.Authority.ADMIN)
                        .anyRequest().authenticated()
                )
                .build();
    }

}
profile
안녕하세요 :)

0개의 댓글