본문 바로가기
JAVA/Spring & Java 학습 기록

스프링 인터셉터를 이용한 권한 검증 분리하기

by 구본식 2023. 6. 14.

문제 상황

사이드 프로젝트를 진행하면서 기본 인증/권한을 제외하고, 방장 및 팀원 권한 검증도 추가로 필요한 상황이였다.

 

초기에는 아래와 같이 Service layer의 메서드를 통해 검증을 진행했다.

하지만, 추가 검증이 필요한 도메인의 Service가 추가될 때 마다 해당 메서드들이 항상 추가되어야 됬었다. 좋지 않아....

 

문제점을 정리해보자.

먼저, 인증 및 권한 검증은 비지니스 로직와 별개의 관심 사항이다. 

또한, 같은 기능의 코드가 계속 반복되어 불필요한 중복 코드가 발생한다.

 

이러한 문제를 Filter, Spring Interceptor, AOP 등을 사용해서 해결할 수 있다.위 기술들 모두 이를 해결할 수 있지만,

컨트롤러에 전달되는 Request, Reponse를 처리하거나, 새로운 데이터 가공, 컨트롤러 호출 과정에서 부가 기능을 위해 사용하는 Spring Interceptor가 더 적절하다고 판단하였다.

방장 및 팀원 검증이 컨트롤러를 호출하기 전에 필요한 부가 기능이기 때문이다.

 

그럼 Spring Interceptor를 통해 이를 해결해보자.

스프링 인터셉터 활용

먼저, 이전에 사용했던 방장 및 팀원 검증 메서드들을 한곳에 모아 스프링 빈으로 등록해보자.

getRecruitment() 메서드를 통해 URL PATH로 전달되는 봉사 모집글 고유번호를 파싱하게 된다.

그럼 이제 인터셉터를 구현해보자.

컨트롤러를 호출하기 전 부가 작업이 필요한 상황이므로, preHandel() 메서드를 오버라이딩하였다.

 

현재 프로젝트에 기본 인증/권한 검사를 Spring Security를 사용하고 있어, Util 함수를 통해 Security Context에서 로그인 사용자 정보를 가져오게 된다.

(만약, 세션 방식을 사용하면 이 부분을 수정하면 된다.)

 

또한, 어노테이션을 새로 정의하여 어노테이션 유무에 따라 로직 실행을 결정하게 되고, 대상(admin,team)에 맞는 메서드를 호출되게 된다.

 

이제 비지니스 로직에 권한 검증이라는 관심사항을 완전히 분리할 수 있게 되었다.

방장 및 팀원 검증일 필요한 컨트롤러에 대해서는 아래와 같이 어노테이션만 붙히면 된다.

(앗... 인터셉터 등록 까먹을뻔 ㅎㅎ)

마지막으로  인터셉터를 등록해보자.

참고로 인터셉터도 필터와 같이 chain으로도 설계할 수 있고, 우선 순위 또한 지정할 수 있다. 또한, 허용/금지 경로를 지정하여 인터셉터 적용을 선택할 수 있다. 

 

사실 허용/금지 경로를 통해 권한 검증이 필요한 URL를 지정해줄 수 도 있지만, 이 방식을 사용한다면 방장과 팀원을 구분하지 못해 각각의 인터셉터가 필요하게 될 것이다.(사실한 거의 동일한 로직이다.)

또한, 문자열을 통해 경로를 직접 입력해야하기 때문에 오타 등의 실수가 발생할 수 있다 생각한다.