[Spring Boot] Spring Security 인증, 인가 예외 처리 클래스 커스텀해서 사용하기

Juice-Han·2025년 1월 13일
0

Spring Boot

목록 보기
4/4
post-thumbnail

인증 받지 않은 유저, 인가 받지 않은 유저를 필터링 하는 좋은 방법이 있어
글로 정리해보고자 한다.

글에서 나오는 SecurityConfig 클래스는 filterChain 메서드를 작성하는
Spring Security의 환경 설정 클래스이다.

클래스명은 사람마다 다를 수 있다는 점을 알아주기 바란다.

사용 버전 정보

  • Spring Boot: 3.4.1
  • Spring Security: 6.4.2
  • Java: 17

인증받지 않은 유저 처리

인증 받지 않은 유저를 처리할 수 있게 해주는 인터페이스가 존재한다.

바로 AuthenticationEntryPoint라는 인터페이스다.

이 인터페이스를 구현하는 클래스를 만들어 Spring Security에 등록하면
인증 받지 않은 유저에 대한 예외 처리가 가능해진다.
ex) 응답 날리기, 리디렉션 하기 등

코드를 보며 예시를 살펴보자.

AuthenticationEntryPoint 구현 클래스 작성

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"로그인이 필요합니다.\"}");
    }
}

@Component 어노테이션을 사용하여 빈으로 등록했다.
이는 SecurityConfig 클래스에서 주입 받아 사용하려는 목적을 가진다.

AuthenticationEntryPoint 인터페이스를 구현하려면 commence라는 메서드를 오버라이딩 해야된다.

나는 response에 Content-Type, Encoding, status 설정을 하고 메세지를 작성해주었다.

이렇게 메서드 내용을 작성한 후 SecurityConfig 클래스에 등록해주면 된다.

등록하는 과정은 인가 관련 클래스를 작성 후 보여주겠다.

인가받지 않은 유저 처리

인가받지 않은 유저를 처리할 수 있게 해주는 인터페이스가 존재한다.

바로 AccessDeniedHandler 인터페이스다.

이 인터페이스도 마찬가지로 구현하는 클래스를 작성 후 SecurityConfig 클래스에 등록해주면
인가 받지 않은 유저에 대한 예외처리를 할 수 있게 된다.

AccessDeniedHandler 구현 클래스 작성

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"권한이 없습니다.\"}");
    }
}

이 클래스도 @Component 어노테이션을 사용해 빈으로 등록했다.

AccessDeniedHandler 인터페이스에는 구현해야할 handle 메서드가 존재한다.

해당 메서드 안에 인가 받지 않은 유저에 대한 처리를 작성하면 된다.

아까와 마찬가지로 response 에 여러 옵션을 설정해줬다.

이렇게 인증과 인가 관련 예외 처리 클래스 작성이 완료됐다.

SecurityConfig 클래스에 등록

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
    private final CustomAccessDeniedHandler customAccessDeniedHandler;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		
        // ~~생략~~

        http
                .exceptionHandling((exceptions) -> exceptions
                        .authenticationEntryPoint(customAuthenticationEntryPoint)
                        .accessDeniedHandler(customAccessDeniedHandler)
                );
                
		// ~~생략~~

        return http.build();
    }
}

SecurityConfig 클래스의 filterChain 메서드 안에 등록하면 된다.

HttpSecurity 객체가 갖는 exceptionHandling 메서드 안에 람다식을 작성하고
구현하는 인터페이스 명과 일치하는 메서드에 알맞은 객체를 전달해준다.

이렇게 하면 인증되지 않은 사용자가 접근하려할 때 혹은
인가받지 않은 사용자가 특정 자원에 접근하려할 때의 예외 처리가 가능
해진다.

사용 이유

Oauth2 로그인을 구현하는 도중,
해당 클래스를 작성하기 전에는 인증 받지 않은 사용자가 접근했을 때
의도치 않게 로그인 페이지로 리다이렉션되는 어려움을 겪었다.

리다이렉션을 방지하고 메세지와 오류 상태코드를 반환하고자 사용하였다.

스프링 시큐리티의 편리함과 기능의 다양성을 느낄 수 있었던 좋은 경험이었다.

참고 자료

  • chb2005님의 블로그글
    해당 자료가 2년 전 자료라 현재 deprecated된 게 존재해서 코드를 살짝 수정하였다.
    SecurityConfig 클래스에 등록 방법: 메서드 체이닝 -> 람다식 사용
profile
배우고 기록하고

0개의 댓글