728x90
AuthenticationEntryPoint는 Spring Security에서 인증(Authentication)에 실패한 사용자가 보호된 리소스에 접근하려고 할 때 어떻게 처리할지를 정의하는 인터페이스입니다. 이는 주로 인증되지 않은 사용자가 보호된 엔드포인트에 접근하려고 할 때 발생하는 상황에 해당합니다.
Spring Security는 보호된 리소스에 접근하려는 모든 요청을 필터링하고, 인증되지 않은 경우에는 AuthenticationEntryPoint를 호출합니다. 이 인터페이스를 구현하는 클래스를 통해 클라이언트에게 어떤 응답을 보낼지를 결정할 수 있습니다.
- 인증되지 않은 사용자 처리: 사용자가 로그인되지 않은 상태에서 보호된 리소스에 접근하려고 할 때 어떤 응답을 생성할지를 정의합니다. 이 응답은 사용자에게 로그인이 필요하다는 것을 알려주는 역할을 합니다.
- 인증 후 권한 없는 사용자 처리: 사용자가 로그인은 했지만 해당 리소스에 필요한 권한이 없는 경우 어떤 응답을 생성할지를 정의합니다. 예를 들어, 관리자 권한이 없는 사용자가 관리자 페이지에 접근하려고 할 때 이에 대한 응답을 정의할 수 있습니다.
AuthenticationEntryPoint를 커스텀으로 구현하면 클라이언트에게 더 나은 사용자 경험을 제공할 수 있습니다. 예를 들어, JSON 형식의 에러 메시지와 함께 상태 코드를 반환하여 클라이언트가 어떤 문제가 발생했는지 이해하기 쉽게 할 수 있습니다. 이를 통해 보안상의 문제와 관련된 정보를 클라이언트와 공유하지 않으면서도 문제 해결을 돕는 역할을 할 수 있습니다.
저는 이 인터페이스를 커스텀으로 구현한 하였습니다.
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
if (authException instanceof UsernameNotFoundException) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(GsonUtil.toJson(new GlobalResponse(HttpStatus.NOT_FOUND, "사용자를 찾을 수 없습니다")));
}else{
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(GsonUtil.toJson(new GlobalResponse(HttpStatus.UNAUTHORIZED, "권한이 없습니다")));
}
}
}
commence 메서드는 다음과 같은 역할을 합니다:
- 인증이 필요한 엔드포인트에 접근하려고 했으나 인증이 실패한 경우 (로그인하지 않은 사용자)
- 인증은 되었지만 해당 사용자의 권한이 요구되는 권한과 일치하지 않는 경우
위의 두 상황에 대해 해당 메서드에서 적절한 응답을 생성하여 클라이언트에게 반환합니다.
- UsernameNotFoundException 처리: 만약 authException이 UsernameNotFoundException 타입일 경우 (사용자를 찾을 수 없는 경우), HTTP 상태 코드를 404로 설정하고, JSON 형식의 응답을 생성하여 "사용자를 찾을 수 없습니다"라는 메시지를 반환합니다.
- 기타 인증 실패 처리: authException이 UsernameNotFoundException이 아닌 경우에는 (권한이 없는 경우) HTTP 상태 코드를 401로 설정하고, JSON 형식의 응답을 생성하여 "권한이 없습니다"라는 메시지를 반환
Security Config에서 클래스를 설정해주었습니다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
...
.exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint())
}