본문 바로가기
IT Study/SpringBoot

Spring Security(4)

by Irwin-Kr 2025. 5. 9.

여태 확인하였던 내용에 대한

Security의 예외 처리에 대해 설명하려고 한다.

 

ExceptionTransactionFilter는

1개의 Security Filter로 FilterChainProxy에 추가되고

HTTP 응답의 AuthenticationException과

AccessDeniedException의

전송을 허용한다.

 

아래 그림으로 다른 Component와의 관계를 알아보자.

 

1️⃣ FilterChain.doFilter(req, resp)를 호출

2️⃣ 사용자가 인증되지 않거나 AuthenticationException인 경우 인증을 수행한다.

3️⃣ AccessDeniedHandler로 접근 거부 처리를 호출한다.

 

⭐️ AccessDeniedException이나 AuthenticationException을 발생하지 않을 경우 ⭐️

ExceptionTranslationFilter는 아무런 동작을 하지 않는다.

 

try{
    // 1. ExceptionTransactionFilter가 호출
    filterChain.doFilter(request, response); 
}catch(AccessDeniedException | AuthenticationException ex){
	if(!authenticated || ex instanceof AuthenticationException){
    	// 2. 인증되지 않은 사용자나 AccessDeniedException인 경우 인증 수행
    	startAuthentication(); 
        /*
           - SecurityContextHolder 삭제
           - 인증이 성공하면 원래 요청을 재사용하도록 HttpServletRequest를 저장
           - AuthenticationEntryPoint는 단말의 자격증명 요청으로 사용 (로그인 페이지로 연결 또는 WWW-Authenticate header 전송)
        */
    }else{
	// 3. 접근 거부.
    	accessDenied();
    }
}

 

 

요청 저장

 

Security Exception 처리에 대한 설명으로

요청에 인증이 없거나 자원에 인증이 요구되는 경우

성공적인 인증에 대한 재요청을 위해 요청을 저장해야한다.

 

RequestCache

HttpServletRequest는 RequestCache에 저장되고,

인증이 성공적이면 RequestCache으로 원본 요청을 다시 수행한다.

 

사용자 인증 후 RequestCacheAwareFilter는

RequestCache에 저장된 HttpServletRequest를 가져오고,

ExceptionTransactionFilter는 사용자를 로그인 끝단으로 이동시키기 전에

RequestCache가 AuthenticationException를 감지하고 HttpServletRequest 저장한다.

 

아래의 예시처럼 continue란 이름의 매개변수가 존재하는 경우

HttpSession에서 저장된 요청을 확인하기 위한 RequestCache 구조에 사용자 정의하는 방법이다.

 

@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
	HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
        // continue의 매개변수 명 확인
	requestCache.setMatchingRequestParameterName("continue");
	http
              .requestCache((cache) -> cache
              .requestCache(requestCache)
		);
	return http.build();
}

 

요청이 미저장

 

세션에 사용자의 인증되지 않은 요청을 저장하지 않는 이유는

 

1️⃣ 데이터베이스에 저장

2️⃣ 저장소에서 사용자 브라우저로 이관

3️⃣ 로그인 전 접속한 페이지 대신 홈페이지로 이동

 

이 있으며, NullRequsetCache로 구현하면 된다.

 

@Bean
SecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
    // NullRequestCache로 요청을 저장하지 않도록 함.
    RequestCache nullRequestCache = new NullRequestCache();
    http
        // ...
        .requestCache((cache) -> cache
        .requestCache(nullRequestCache)
        );
    return http.build();
}

 

 

Logging

Spring Security는 모든 보안과 관련된

DEBUG와 TRACE level의 종합적인 logging을 제공

 

 Spring Security의 보안 조치는 응답 내용에 요청 거부의 상세 정보도 추가하지 않기에

logging은 매우 유용하다.

 

401이나 403의 오류에 대해 이해하는데 도움을 주는데,

예를 들면 사용자가 CSRF 보호가 활성화된 자원에 CSRF token 없이 POST 요청하였을 경우

logging이 없으면, 사용자는 요청이 왜 거부된 설명도 없이 403 오류를 볼수 밖에 없지만

Spring Security에 logging이 활성화 되어있으면 로그 메시지를 확인할 수 있다.

 

아래의 예시 처럼 요청이 CSRF token이 없어 요청이 거부됨을 알수 있다.

2023-06-14T09:44:25.797-03:00 DEBUG 76975 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing POST /hello
2023-06-14T09:44:25.797-03:00 TRACE 76975 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/15)
2023-06-14T09:44:25.798-03:00 TRACE 76975 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/15)
2023-06-14T09:44:25.800-03:00 TRACE 76975 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/15)
2023-06-14T09:44:25.801-03:00 TRACE 76975 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/15)
2023-06-14T09:44:25.802-03:00 TRACE 76975 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking CsrfFilter (5/15)
2023-06-14T09:44:25.814-03:00 DEBUG 76975 --- [nio-8080-exec-1] o.s.security.web.csrf.CsrfFilter         : Invalid CSRF token found for http://localhost:8080/hello
2023-06-14T09:44:25.814-03:00 DEBUG 76975 --- [nio-8080-exec-1] o.s.s.w.access.AccessDeniedHandlerImpl   : Responding with 403 status code
2023-06-14T09:44:25.814-03:00 TRACE 76975 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match request to [Is Secure]

 

 

위의 로그를 기록하기 위하여 아래와 같이 추가하면 된다.

 

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 기타 설정들... -->
    </appender>
    <!-- 기타 설정들... -->
    <logger name="org.springframework.security" level="trace" additivity="false">
        <appender-ref ref="Console" />
    </logger>
</configuration>

 

 

'IT Study > SpringBoot' 카테고리의 다른 글

Spring Security 인증 구조 - 2  (0) 2025.06.28
Servlet 인증 구조  (2) 2025.06.14
Spring Security(3)  (0) 2025.04.26
Spring Security (2)  (0) 2025.04.11
Spring Security (1)  (0) 2025.03.28