스프링 로그인 권한 검사에 대한 설계 방법
스프링을 개발해오면서 봐왔던 로그인 권한 검사에 대해 설계 방법을 정리할 겸 적어보고자 합니다.
특정 방식이 무조건 좋거나 혹은 무조건 나쁘다고 할 수 없을 만큼 각각의 방식들이 Trade-Off가 존재합니다.
아래의 리스트 중 API 권한 검사에 대한 코드만 Github에 올려놨으니 참조하시길 바랍니다.
계정에 대한 DB는 H2를 이용 했으니 아래와 같이 사용해주세요.
Session을 이용한 권한 검사
① Interceptor에서 Redirect 처리
가장 일반적인 방식에 속한다.
Session 방식을 이용한 권한 검사 방식에서는 로그인한 사용자의 정보를 Session에 담게 되는데,
Interceptor에서 해당 Session 정보가 존재하지 않는다면 로그인 화면으로 보내는 방식으로 개발한다.
② 여러개의 권한 검사
개발을 하다보면 항상 로그인이 필요한 페이지만 있을 수는 없다.
특정 페이지는 로그인을 하지 않아도 볼 수 있어야 하고 또 다른 페이지에선 특정 사용자만 볼 수 있는 페이지가 있을 수 있어야 한다.
이런 경우 하나의 Interceptor 내에서 모든 권한에 대해서 분기처리 할 수도 있다. 다만, 서비스 사이즈가 커진다면 모든 로직이 Interceptor를 거치는 것은 부하를 일으킬 것이다. 로그인을 하지 않아도 볼 수 있는 페이지는 Interceptor를 거치지 않도록 구현하는 것이 서비스 속도 측면에서 더 좋기 때문에 아예 Interceptor를 거치지 않도록 만들어야 한다.
특정 API 주소마다 Interceptor를 거치지 않게 하려면 Controller를 결정하게 되는 Handler Mapping을 Customize해서 인입되는 주소마다 특정 Interceptor를 타도록 구현해야한다.
대표적인 방식이 과거에 전자정부 프레임워크에서 소스를 공개한 인터셉터 분리 방식이다.
이러한 방식은 API 주소를 죄다 등록해줘야 하는 단점이 있는데, 최근 스프링부트에서는 패키지 자체를 등록하는 기능도 나왔으니 해당 방식을 이용하면 더 깔끔한 소스를 만들 수 있다.
③ View 화면에서 Session 검사하기
보통 Session을 이용한 방식은 대개 클라이언트와 서버가 강결합되어있는 SSR에서 사용하는 방식이다.
그렇기 때문에 서버에 존재하는 Session을 화면 영역에서도 가져올 수가 있는데, 페이지 영역에서 Session에 대한 정보를 판단하는 공통 페이지를 만들어 각각의 페이지마다 공통 페이지를 포함시켜 권한 검사를 할 수 있다.
사용 방법은 굉장히 간단하지만 당연히 API성 조회 방식에서는 사용할 수도 없고 소스 관리도 힘들기에 작은 규모의 서비스에서 권장할 수는 있다.
API 권한 검사
① Spring Security 권한 검사
Spring Security를 기능을 이용하면 특정 API 경로로 진입 시에 권한을 아래와 같이 자동으로 필터링 해줄 수 있다.
하지만 단점이 있다면 이렇게 손쉽게 공통처리 되는 것들을 사용한다면 추후에 서비스가 커질 경우 세부적인 권한 관리가 더 복잡해질 수 있어서 사용하는 것을 권장하지 않는다.
② Spring Method Security
Spring Security 설정을 통해 한번에 권한 검사를 하는게 싫다면 Spring Method Security를 이용해 각각의 API마다 권한 검사를 수행할 수 있다.
Spring Method Security를 이용하기 위해서는 아래와 같은 클래스를 만들어 줘야한다.
설정이 끝났다면 각각의 EndPoint마다 검사를 하기 위해 아래와 같이 사용할 수 있다.
하지만 Spring Method Security를 사용할 시에 속성 값에 Enum을 넣는 것은 조금 복잡하다.
속성 값으로 Enum을 넣기 위해선 Enum 값을 바로 넣을 수 없고 Enum의 메소드를 이용해서 넣어줘야하는데, Enum의 열거 속성을 Final 즉, 상수로 만들어줘야하는 수작업이 필요하다.
관련 내용은 어노테이션의 요소는 항상 상수여야 하는가?을 참조하고 Github에 있는 예제를 확인하자.
③ AOP를 이용한 권한 검사
Spring Method Security는 Spring Security를 통한 로그인인 경우에만 판단할 수 있다.
왜냐면 Security의 UserDetails로부터 얻어진 권한을 통해 검사하기 때문이다.
그렇기에 기존에 로그인 방식을 Security로 구성하지 않고 어노테이션을 이용해 권한 검사를 하고 싶다면 수동으로 만들어서 사용할 수 있다.
우선은 아래와 같이 어노테이션을 직접 만들어준다.
그리고 컨트롤러에서 Spring Method Security에서 사용하던 것처럼 사용한다.
그리고 어노테이션이 적용된 메소드마다 AOP를 타도록 AOP 클래스를 만들어준다. Github에 있는 예제 코드는 Security를 검사하는 코드로 짜여져 있지만 Security가 아니더라도 세션이든 뭐든 Login 객체를 판별할 수 있는 로직을 안에 작성한다면 손쉽게 어노테이션을 이용해서 권한 검사를 할 수 있다.
참고