[Spring Security] 에러 - 로직 수행 이후 403 Forbidden 발생 원인

박상훈·2024년 8월 24일

에러 로그

목록 보기
9/13

상황

  • 스프링 시큐리티를 적용하여 필터를 구성하고 Security Config 파일 작성을 마쳤다. Postman을 사용하여 api 테스트를 진행해보았는데, 회원 가입 페이지, 로그인 페이지는 모두 .prtmitAll()을 통해 요청 허가를 했는데도 불구하고 403 Forbidden에러가 난 것이다.

  • 로그를 살펴보니 회원 가입 로직은 잘 수행되어 DB에 저장된 모습을 볼 수 있었다. 그런데 왜 200 응답이 아닌 403 응답이 오게 된 것일까?

에러 발생 원인

  • 에러 자체가 발생한 원인은 아래 제작된 컨트롤러 메소드를 보면 리턴값이 Dto인데 @ResponseBody 가 없어서 404 에러가 발생하게 되는 상황이었다.
	@PostMapping
    public UserDto.Response createUser(@RequestBody UserDto.Create userDto) {

        UserDto.Response createdUser = userService.createUser(userDto);
        log.info(createdUser.toString());

        return createdUser;
    }

?? 그렇다면 왜 404 에러가 나지 않고 403에러가 나서 삽질을 하게 만든 것일까?

  • 기본적으로 스프링에서는 따로 예외 처리를 하지 않았다면 예외 발생 시 500 에러가 발생한다. 그런데 스프링 시큐리티를 적용하면 메소드에서 예외가 발생했을 때 403 에러가 발생한다. 심지어 존재하지 않는 URL로 접속하여 404 Not Found가 발생해야 하는 상황에서도 403 Forbidden이 발생한다.

403 에러가 발생하는 원인

우선 이 현상의 원인을 파악하기 위해선 스프링부트에서 에러가 발생했을 때 나타나는 Whitelabel Error Page가 어떻게 나타나는지 알아야한다.

스프링 공식 블로그에 따르면 스프링부트에서는 에러가 발생하면 /error라는 URI로 매핑을 시도한다. 실제로 해당 URI로 이동하면 아래와 같은 페이지가 나타난다.

따로 에러가 발생하여 자동으로 나타난 것이 아니라 강제로 이동했기 때문에 status가 999로 나타났지만 굉장히 익숙한 Whitelabel Error Page가 나타난다.

  • Whitelabel Error Page 자체는 403에러와 관련이 없지만 에러가 발생하면 /error로 매핑을 시도한다는 것이 핵심이다.

  • 일반적으로 permitAll()을 통해 모든 사용자의 접근을 허용할 URI에는 권한 검증이 필요하지 않은 URI만 추가한다. 그리고 위에서 언급했듯이 스프링부트 프로젝트에서는 에러 발생 시 /error로 매핑한다. 그런데 /error는 모두에게 허용된 URI에 포함되지 않는다.

  • 그래서 결과적으로 에러 페이지에도 인증 절차가 요구되어 403에러가 발생하는 것이다.


해결 방법

일단 이 문제는 anyRequest().authenticated()로 인해 /error도 인증이 필요한 것으로 간주되어 발생한 것이기 때문에 모두에게 허용할 URI 목록에 /error를 추가하면 해결할 수 있다.

	.requestMatchers("/error").permitAll() // 에러 페이지 요청 허가
profile
안녕하세요

0개의 댓글