녕의 학습 기록
[whatssue] 스프링 인터셉터를 사용해 사용자 권한 체크하기 본문
문제 상황
모임 관리 프로젝트의 모임 관련 api를 개발하다가 다음과 같은 문제를 직면했다.
1. 매번 club이 존재하는지 체크해주어야한다.
2. 매번 로그인 유저가 이 club의 멤버인지 체크해주어야 한다.
3. 매번 로그인 유저가 이 club의 관리자인지 체크해주어야 한다. (관리자 api인 경우)
4. 매번 로그인 유저가 이 club에 가입 이후 처음 방문했는지 체크해주어야 한다.
클럽에 관련된 api마다 1, 2, 3, 4의 중복 코드가 발생한다.
해결방안
중복되는 공통 관심사를 한번에 처리하고자 하였다.
조금 찾아보니 필터, 스프링 인터셉터, AOP 로 공통관심사를 처리할 수 있었고,
나는 스프링 인터셉터(Spring Interceptor)를 사용하여 이번 문제를 해결하고자 하였다.
스프링 인터셉터란 ?
스프링 인터셉터(Spring Interceptor)는 스프링 MVC가 제공하는 기술로,
웹의 공통 관심사항을 해결하기 위해 사용한다.
스프링 인터셉터 흐름
[ 요청 -> was -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러 ]
서블릿 이전에 호출되는 필터와 달리 스프링 MVC가 제공하는 기술이기에 Dispatcher Servlet 이후에 호출된다.
따라서 컨트롤러 호출 전에 로그인 체크, 권한 체크, 로깅 등 공통 관심사항을 처리하기에 유용하다.
스프링 인터셉터 호출 흐름
인터셉터는 다음의 세가지 경우로 세분화되어 호출된다.
- preHandle : 컨트롤러 호출 이전 (핸들러 어댑터 호출 이전)
- postHandle : 컨트롤러 호출 이후 (핸들러 어댑터 호출 이후)
- afterCompletion : 뷰 렌더링 이후 (예외 발생시에도 무조건 호출된다)
스프링 인터셉터의 특징(장점)
- HttpServletRequest/Response와 Handler 등 다양한 파라미터를 받을 수 있다.
- Web Config에 등록할 때 addPathPatterns와 excludePathPatterns를 통해
적용 URL 패턴을 편리하고 세밀하게 지정할 수 있다. - 추후 생각나면 기입..
프로젝트에 적용
ClubCheckInterceptor의 preHandle를 구현해 컨트롤러 호출 이전에
존재하는 club인지,
로그인 유저가 club의 memeber인지,
관리자 api인 경우 로그인 유저가 manager 인지,
club 가입 이후에 첫 방문 인지를 체크했다.
인터셉터 구현
- HTTP 요청이 호출하는 HandlerMethod가 ClubManager 커스텀 애노테이션을 가지고 있으면 관리자 권한 체크를 진행하도록 했다
- 빈으로 등록한 ClubCheckInterceptor를 생성자 주입 받아 WebConfig에 등록해주었다.
- order 를 주어 ScheduleCheckInterceptor와 우선순위를 주었다.
고민했던 점 및 알게된 점
1. 인터셉터에서 바로 repository에 접근해도 될까?
-> 인터셉터는 인증과 권한 부여의 역할까지만으로 분리하는 것이 좋다. db 접근은 서비스 레이어 등에서 하는 것이 좋다!
2. 클럽 존재여부 체크, 클럽 멤버 체크, 클럽 관리자 체크 등을 각각의 인터셉터로 구현해야할까?
-> 처리하려는 사항들이 상당히 밀접한 기능들이기에 한 곳에서 구현하는 것이 효율적이고 코드 중복도 방지 가능!
3. preHandle 은 컨트롤러 호출 이전에 호출되므로 예외를 던져도 @ExceptionHandler 에서 처리하지 못할텐데 예외처리를 어떻게 하면 좋을까?
-> 컨트롤러 호출 이전에 호출되기 때문에 컨트롤러 내의 @ ExceptionHandler에서는 인터셉터에서 던지는 예외를 처리할 수 없다. 하지만 @ControllerAdvice 또는 @RestControllerAdvice를 달고 있는 GlobalExceptionHandler에서는 앱 전역에서 발생하는 예외를 처리하기 때문에 스프링 인터셉터에서 던지는 예외를 처리할 수 있다!!
따라서 그냥 예외를 던져주었다.
'Dev > Spring' 카테고리의 다른 글
.properties 파일 인코딩 문제 해결 (0) | 2023.07.28 |
---|---|
[Spring] Spring 프로젝트 생성 및 설정 (0) | 2023.03.05 |
[Spring MVC 1] 스프링 MVC 웹 페이지 만들기 (1) | 2023.02.17 |
[Spring MVC 1] 스프링 MVC-기능 (4) (0) | 2023.02.08 |
[Spring MVC 1] 스프링 MVC-기능 (3) (0) | 2023.02.07 |