[spring security] 왜 500번 에러도 401(Unauthorized)에러가 될까?

2024. 4. 7. 20:31·spring

문제상황

spring security에서 filterChain을 설정하면서 "/member/signUp" url에 대한 request는 permitAll()을 해주고 싶었다.

 

이 과정에서 분명 permitAll()를 해주었지만 401 error가 발생하였고 이를 해결하는 과정을 포스팅한다.

 

본문

String[] allowUrls = {"/", "/swagger-ui/**", "/member/signUp"};

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    http
            .csrf(AbstractHttpConfigurer::disable)
            .cors(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(request -> request
                    .requestMatchers(allowUrls).permitAll()
                    .anyRequest().authenticated())
            .addFilterBefore(loginAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling(config -> config
                    .authenticationEntryPoint(authenticationEntryPoint)
                    .accessDeniedHandler(accessDeniedHandler));

    return http.build();
}

 

현재 springConfig 클래스의 filterChain을 설정하는 코드입니다.

 

 

swagger를 통해 request를 보냈을 시 401 에러가 발생합니다.

 

MDN의 설명에 따르면 401 에러는 다음과 같은 상황에서 발생한다.

 

 
401 Unauthorized :
 응답 상태 코드는 요청된 리소스에 대한 유효한 인증 자격 증명이 없기 때문에 클라이언트 요청이 완료되지 않았음을 나타냅니다.

 

 

permitAll()을 했는데 401이 뜬다라..

 

다시 로그를 확인을 해보았습니다.

 

 

Filter를 거치면서 AuthorizationFilter에서 권한을 확인하는 로그가 찍히던 중 DB에 조회 쿼리가 나가는 것을 확인할 수 있었습니다.

 

스프링 구조 (사진 출처 : https://gowoonsori.com/blog/spring/architecture/)

 

스프링 요청의 처리 구조를 보면 DB에 쿼리가 나간다는 것은 요청이 FilterChain을 거쳐 Spring container의 서비스 레이어까지 도달했다는 것이다.

 

이 말은 FilterChain에 속하는 spring security는 이미 지나쳤다는 말이므로 permitAll() 메서드는 정상 작동하였다.

 

문제 지점 확인

 

Post /member/signUp request가 filter를 거친 후 추가로 Post /error request가 filter를 거치는 것을 볼 수 있었다.

 

Spring Boot는 예외가 발생하면 구체적인 Exception Handler가 존재하지 않을 시 /error 경로로 다시 에러를 재요청한다.

 

Spring Boot의 Basic Error 처리 흐름

 

한번 WAS(톰캣)를 거쳤던 request가 다시 WAS(톰캣)을 거치게 되는 것이다.

 

이 과정에서 필터를 거치며 security filter를 거치게 되고 /error URI는 permitAll()이 되지 않았기 때문에 AccessDeniedException를 던지게된다.

 

최종 문제 발생 원인

ExceptionHandler를 만들어주지 않았기 때문이다.

 

/member/signUp으로 request를 보내면 직접 만들어둔 customException인 NotFoundException이 발생한다.

 

하지만 이를 만들어놓고 해당 예외를 처리해주는 ExceptionHandler를 만들지 않았기 때문에 spring boot의 기본 에러 방식 작동하였다.

 

@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 아래와 같은 형식의 예외를 프론트에 던져줍니다
     * {
     * "message": "해당 부서를 찾을 수 없습니다.",
     * "httpStatus": "NOT_FOUND",
     * "timestamp": "2024-02-28T15:28:59.140106",
     * "detail": "해당 Id의 부서가 존재하지 않습니다."
     * }
     */
    @ExceptionHandler
    protected ResponseEntity<ErrorResponse> handleCustomException(CustomException e) {
        ErrorCode errorCode = e.getErrorCode();
        ErrorResponse errorResponse = ErrorResponse.of(errorCode, LocalDateTime.now());
        errorResponse.setDetail(e.getMessage());
        return new ResponseEntity<>(errorResponse, errorCode.getStatus());
    }
}

 

위와 같은 GlobalExceptionHandler 클래스를 만들고 CustomException을 처리해주는 메서드를 작성해주면 NotFoundException이 404 에러로 제대로 처리되는 것을 볼 수 있다.

 

404 에러가 나오는 모습

 

 

 

'spring' 카테고리의 다른 글

Java reflection을 통해 RestDocs 생성 테스트 코드 작성 시간 1/2로 줄이기  (2) 2024.09.27
[스프링] service 인터페이스 도입과 접근제한자  (1) 2024.09.20
이미지 저장/조회 서버 만들기(3) - AWS Presigned URL 이미지 업로드  (0) 2024.02.26
이미지 저장/조회 서버 만들기(2) - 이미지 파일 어떻게 받아오지?  (0) 2024.02.12
이미지 저장/조회 서버 만들기(1) - 저장 어디에..?  (0) 2024.02.11
'spring' 카테고리의 다른 글
  • Java reflection을 통해 RestDocs 생성 테스트 코드 작성 시간 1/2로 줄이기
  • [스프링] service 인터페이스 도입과 접근제한자
  • 이미지 저장/조회 서버 만들기(3) - AWS Presigned URL 이미지 업로드
  • 이미지 저장/조회 서버 만들기(2) - 이미지 파일 어떻게 받아오지?
박세준
박세준
  • 박세준
    박세준의 개발 메이커로그
    박세준
  • 전체
    오늘
    어제
    • 분류 전체보기 (14)
      • spring (10)
      • java (1)
      • 프로젝트 (3)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    FastAPI
    엔티티와 밸류
    BasicErrorController
    spring 문서화
    이미지처리
    spring security
    팩토리 클래스
    레이어드 아키텍처
    Sentry
    REST Docs
    denied Access
    ssl 인증서 재발급
    Bucket Policy
    SSL 인증서 발급
    에러 수집
    aws
    애그리거트간 연관관계
    certbot
    On premise
    애그리거트
    permitAll
    도메인 주도 개발
    java
    트랜잭션 범위
    MultipartFile
    S3
    Spring
    Spring Boot
    SWAGGER
    Python
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
박세준
[spring security] 왜 500번 에러도 401(Unauthorized)에러가 될까?
상단으로

티스토리툴바