SecurityConfig 설정

2025. 2. 16. 17:07·개발기록/SweetBalance

지난 포스팅인 인증/인가 로직 구현에 이어 Spring Security의 핵심 설정 클래스인 SecurityConfig에 대해 간단히 정리해보고자 한다.


필드 및 생성자

하단 CORS에 적용할 프론트 측 오리진 문자열은 yml 파일로 부터 가져오도록 작성하였고, 

AuthenticationConfiguration의 경우 Spring Security의 기본 인증 설정이 주입된다.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Value("${spring.front.origin-http}")
    private String frontOriginHttp;

    @Value("${spring.front.origin-https}")
    private String frontOriginHttps;

    private final AuthenticationConfiguration authenticationConfiguration;
    private final CustomOAuth2UserService customOAuth2UserService;
    private final CustomSuccessHandler customSuccessHandler;
    private final JWTUtil jwtUtil;

    @Autowired
    public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, CustomOAuth2UserService customOAuth2UserService,
                          CustomSuccessHandler customSuccessHandler, JWTUtil jwtUtil) {
        this.authenticationConfiguration = authenticationConfiguration;
        this.customOAuth2UserService = customOAuth2UserService;
        this.customSuccessHandler = customSuccessHandler;
        this.jwtUtil = jwtUtil;
    }
	
    // 이하 내용 생략
}

Bean Definition

SecuritFilterChain을 제외한 빈에는 AuthenticationManager와 BCryptPasswordEncoder를 추가해주었다.

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
    return configuration.getAuthenticationManager();
}

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
    return new BCryptPasswordEncoder();
}

// 하단엔 SecurityFilterChain 설정

 


SecurityFilterChain 설정

CORS 설정

프론트 통합 과정에서 가장 기본적으로 발생하는 문제인 CORS 설정 관련 부분이다.

WebMvcConfigurer를 구현한 Config 클래스의 `addCorsMappings()` 메소드도 따로 설정해주어야 한다.(이 포스팅에서는 제외했다)

httpSecurity
        .cors(corsCustomizer -> corsCustomizer.configurationSource(new CorsConfigurationSource() {

            @Override
            public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {

                CorsConfiguration configuration = new CorsConfiguration();

                configuration.setAllowedOrigins(List.of(frontOriginHttp, frontOriginHttps));
                configuration.setAllowedHeaders(Collections.singletonList("*"));
                configuration.setAllowedMethods(Collections.singletonList("*"));
                configuration.setAllowCredentials(true);
                configuration.setMaxAge(3600L);

                configuration.setExposedHeaders(Arrays.asList("Authorization", "Set-Cookie"));

                return configuration;
            }
        }));

경로별 인가 작업 및 Exception Handling

인증/인가가 필요한 엔드포인트에 `hasAnyAuthority()` 를 통해 설정을 추가하였으며, 그 이외의 요청에 대해서는 검증을 진행하지 않도록 하였다. 처음에는 anyRequest에 `authenticated()` 설정을 해주었다가, 존재하지 않는 엔드포인트에 대해서도  401이나 403 응답이 가는 문제를 발견하여 `permitAll()`로 변경, 정상적으로 404 응답이 가도록 수정하였다.

httpSecurity
        .authorizeHttpRequests((auth) -> auth
                .requestMatchers("/api/auth/sign-out").hasAnyAuthority(ADMIN.getValue(), USER.getValue())
                .requestMatchers("/api/auth/withdraw").hasAnyAuthority(ADMIN.getValue(), USER.getValue())
                .requestMatchers("/api/user/**").hasAnyAuthority(ADMIN.getValue(), USER.getValue())
                .requestMatchers("/api/beverages/**").hasAnyAuthority(ADMIN.getValue(), USER.getValue())
                .anyRequest().permitAll())

        .exceptionHandling(customizer -> customizer
                .authenticationEntryPoint((request, response, authException) -> {
                    // 인증 실패 처리 (401 Unauthorized)
                    InnerFilterResponseSender.sendInnerResponse(response, 401, 999,
                            "인증이 필요합니다. 로그인해주세요.", null);
                })
                .accessDeniedHandler((request, response, accessDeniedException) -> {
                    // 권한 부족 처리 (403 Forbidden)
                    InnerFilterResponseSender.sendInnerResponse(response, 403, 999,
                            "권한이 부족합니다.", null);
                }));

기타 HttpSecurity 설정

CORS 설정과 경로별 인가 설정 외에도 다른 설정들을 필터 체인에 추가하였다.

		//CSRF(Cross-Site Request Forgery) 보호 기능 비활성화
        httpSecurity
                .csrf((auth) -> auth.disable());

        //Spring Security의 기본 폼 로그인 방식(Username & Password 로그인 폼) 비활성화
        httpSecurity
                .formLogin((auth) -> auth.disable());

        //HTTP Basic 인증 방식 비활성화
        httpSecurity
                .httpBasic((auth) -> auth.disable());
        
        //OAuth2 로그인 설정
        httpSecurity
                .oauth2Login((oauth2) -> oauth2
                        .userInfoEndpoint((userInfoEndpointConfig) -> userInfoEndpointConfig
                                .userService(customOAuth2UserService))
                        .successHandler(customSuccessHandler)
                );

        //LoginFilter 추가 - 일반 로그인
        httpSecurity
                .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil), UsernamePasswordAuthenticationFilter.class);

        //CustomLogoutFilter 추가
        httpSecurity
                .addFilterBefore(new CustomLogoutFilter(jwtUtil), LogoutFilter.class);

        //JWTFilter 추가
        httpSecurity
                .addFilterAfter(new JWTFilter(jwtUtil), OAuth2LoginAuthenticationFilter.class);

        //세션을 사용하지 않는 방식(STATELESS)으로 설정
        httpSecurity
                .sessionManagement((session) -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS));

마치며

테스트 진행 시 보안관련 설정이 어떻게 잘 구성되어 있느냐에 따라 백엔드 작업자 측에서도, 프론트 측에서도 영향을 많이 받는 것 같다. 프로젝트 진행 초반에 정확히 설정하고 넘어가야 이후 진행이 수월하다고 느꼈다.

 

 

 

 

'개발기록/SweetBalance' 카테고리의 다른 글
  • 리프레시 토큰 저장소 Redis 적용
  • 셀레니움을 활용한 크롤링 시스템 구현
  • Spring Security와 JWT를 통한 인증/인가 로직 구현
kisusu
kisusu
  • kisusu
    KISUSU
    kisusu
  • 전체
    오늘
    어제
    • 분류 전체보기 (9)
      • 개발기록 (4)
        • SweetBalance (4)
      • 개발공부 (2)
      • 개념정리 (2)
      • 알고리즘 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    CRUD
    NoSQL
    리프레시 토큰
    JWT
    Selenium
    SecurityConfig
    CORS
    인증
    redis
    스프링
    mongoDB
    통합 로그인 구현
    Top-Down
    셀레니움
    node.js
    스프링 시큐리티
    인가
    개발공부
    개발자 유미
    개념정리
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
kisusu
SecurityConfig 설정
상단으로

티스토리툴바