본문 바로가기

Spring Boot

[Spring Boot] 스프링 시큐리티 설정

728x90

스프링 시큐리티(Spring Security)란?

스프링 시큐리티는 스프링 기반 웹 애플리케이션의 인증(Authentication)과 인가(Authorization) 를 담당하는 하위 프레임워크입니다.

  • 인증 (Authentication) : 사용자의 신원을 확인하는 과정 (예: 로그인)
  • 인가 (Authorization) : 인증된 사용자가 애플리케이션에서 어떤 행동을 할 수 있는지 권한을 부여하는 과정

 

스프링 시큐리티 기본 설정

  1. 스프링 시큐리티 의존성 추가
    implementation 'org.springframework.boot:spring-boot-starter-security'
  2. 기본 로그인 화면
    • 스프링 시큐리티 의존성을 추가하고 애플리케이션을 실행하면, 모든 경로에 기본 로그인 화면이 나타나며 인증을 요구합니다.
    • 인증되지 않은 사용자는 웹 서비스 접근이 불가하므로, 인증 설정을 통해 접속을 허용할 특정 경로를 설정해야 합니다.

 

 

스프링 시큐리티 설정 코드 예제

스프링 시큐리티의 동작을 제어하려면 @Configuration과 @EnableWebSecurity 어노테이션을 사용하여 보안 설정 파일을 작성해야 합니다.

기본 경로 접근 설정

모든 URL에 대해 인증을 해제하는 예제입니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
                        .requestMatchers(new AntPathRequestMatcher("/**"))
                        .permitAll()
                );
        return http.build();
    }
}

 

  • @Configuration : 이 파일이 스프링의 설정 파일임을 나타냅니다.
  • @EnableWebSecurity : 모든 요청 URL이 스프링 시큐리티의 제어를 받게 만듭니다.

 

H2 콘솔 접근 문제 해결하기

1. 403 Forbidden 오류 해결

  • 스프링 시큐리티는 CSRF(Cross-Site Request Forgery) 공격 방어 기능을 기본으로 활성화하고 있습니다. 그러나 H2 콘솔은 CSRF 토큰을 발행하지 않아, 기본 설정으로 접근 시 403 Forbidden 오류가 발생합니다.
  • CSRF 보호 해제 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(authorizeRequests -> authorizeRequests
                        .requestMatchers("/h2-console/**").permitAll() // H2 콘솔에 대한 접근 허용
                )
                .csrf(csrf -> csrf
                        .ignoringRequestMatchers(new AntPathRequestMatcher("/h2-console/**"))
                ); // H2 콘솔에 대한 CSRF 보호 비활성화

        return http.build();
    }
}

 

 

 

2. 프레임 화면 깨짐 오류 해결

H2 콘솔 UI는 프레임 구조로 작성되었으며, 스프링 시큐리티는 다른 사이트의 콘텐츠가 포함되지 않도록 X-Frame-Options 헤더의 기본값을 DENY로 설정합니다. 이를 통해 외부 사이트가 웹 애플리케이션을 iframe으로 로드하는 것을 방지할 수 있습니다.

  • 헤더 설정 변경
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(authorizeRequests -> authorizeRequests
                        .requestMatchers("/h2-console/**").permitAll() // H2 콘솔에 대한 접근 허용
                )
                .csrf(csrf -> csrf
                        .ignoringRequestMatchers(new AntPathRequestMatcher("/h2-console/**"))
                ) // H2 콘솔에 대한 CSRF 보호 비활성화
                .headers(headers -> headers
                        .addHeaderWriter(new XFrameOptionsHeaderWriter(
                                XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN
                        ))
                ); // X-Frame-Options 헤더를 SAMEORIGIN으로 설정하여 오류 해결

        return http.build();
    }
}
  • X-Frame-Options 헤더 값으로 SAMEORIGIN을 설정하여 동일한 사이트 내에서는 프레임 구조가 허용됩니다.

 

다양한 요청 경로에 대한 접근 제어

SecurityConfig 클래스는 스프링 시큐리티 설정을 정의하고, 다양한 요청 경로에 대한 접근을 제어하여 특정 경로는 인증 없이 접근할 수 있도록 설정합니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;

import java.util.List;

@Configuration
@EnableWebSecurity // 스프링 시큐리티 활성화
public class SecurityConfig {

    // 인증 없이 접근 허용할 경로 리스트
    private final List<String> SWAGGER = List.of(
            "/swagger-ui.html",
            "/swagger-ui/**",
            "/v3/api-docs/**"
    );

    private final List<String> OPEN_API = List.of(
            "/open-api/**"
    );

    private final List<String> DEFAULT_EXCLUDE = List.of(
            "/",
            "/favicon.ico",
            "/error"
    );

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeHttpRequests(it -> {
                    it.requestMatchers(
                            PathRequest.toStaticResources().atCommonLocations()
                    ).permitAll() // 정적 리소스는 모두 접근 허용

                    // SWAGGER 관련 경로는 인증 없이 접근 허용
                    .requestMatchers(SWAGGER.toArray(new String[0])).permitAll()

                    // OPEN-API 관련 경로도 인증 없이 접근 허용
                    .requestMatchers(OPEN_API.toArray(new String[0])).permitAll()

                    // 기본 경로와 에러 페이지 등은 인증 없이 접근 허용
                    .requestMatchers(DEFAULT_EXCLUDE.toArray(new String[0])).permitAll()

                    // 그 외 모든 요청은 인증 필요
                    .anyRequest().authenticated();
                })
                .formLogin(Customizer.withDefaults()); // 기본 로그인 페이지 설정

        return httpSecurity.build();
    }
}

 

코드 설명

  • SWAGGER, OPEN_API, DEFAULT_EXCLUDE : 각각의 리스트로 설정된 경로들은 인증 없이 접근이 허용됩니다.
  • Static Resources 허용 : PathRequest.toStaticResources().atCommonLocations()로 지정된 정적 리소스 경로에 대해서는 모든 사용자가 접근할 수 있습니다.
  • 나머지 요청에 대한 인증 필요 설정 : .anyRequest().authenticated()를 통해 명시되지 않은 다른 모든 경로에 대해 인증을 요구합니다.
  • 기본 로그인 페이지 사용 : .formLogin(Customizer.withDefaults()) 설정을 통해 기본 로그인 페이지를 제공합니다.

이 구성을 통해 여러 경로에 대해 개별적으로 접근 제어를 설정할 수 있으며, 기본 로그인과 인증 설정을 통해 보안 기능을 관리할 수 있습니다.

728x90