이전까지 인증에 대하여 계속 공부해봤다 이제인가 처리를 한번 공부해보자 한다
인가는 말그대로 사용자가 로그인 했을때 서버자원에 접근할수 잇는 자격이 있는지 여부를 판단하는게 인가처리 라고 할수있다.
그래서 SprginSecurity는 Authentication과 Authorization 두개를 처리하도록 되어 있다. 위에 그림을 보면 사용자가 서버 자원에 접근하려 할때 그 사용자가 Authenticated 먼저 인증을 받았는지 안받았는지 확인을 하게된다 이후에 Authorization 에서 해당자원에 설정된 권한에 충분한 자격이 있는지 권한 심사를 하게된다.
스프링 시큐리티가 지원하는 권한계층을 살펴보자
- 웹 계층
- URL 요청에 따른 메뉴 혹은 화면단위의 레벨보안
- 사용자가 user라는 경로로 자원에 접근하려고 할때 요청을 했을때 그자원에 설정된 권한과 사용자가 허가된 권한과 비교를 해서 접근유무를 판단해서 결정한다
- 서비스 계층
- 화면 단위가 아닌 메소드 같은 기능 단위의 레벨 보안
- 사용자가 user라는 메소드에 진입하고자 할때 메소드에 설정된 권한과 사용자가 가진 권한을 비교해서 일치하는지 판단해서 인가처리를 한다
- 도메인 계층(AccessControlList,접근제어 목록)
- 객체 단위의 레벨 보안
- user객체를 파일이나 폴더 데이터 베이스 같은 어플리케이션에 접근하여 사용하고자 할때 도메인에 설정된 권한과 사용자가 가진 권한을 비교해서 도메인을 사용유무를 판단한다
FilterSecurirtyInterceptor
- 마지막에 위치한 필터로써 인증된 사용자에 대하여 특정 요청의 승인/ 거부 여부를 최종적으로 결정
- 인증객체 없이 보호자원에 접근을 시도할 경우 AuthenticationException을 발생
- 권한 제어 방식중 HTTP 자원의 보안을 처리하는 필터
- 권한 처리를 AccessDecisionManager에게 맡김
이필터는 인가 처리를 담당하는 필터다 사용자가 요청을 하게 될때 각 필터들에 대해서 처리가 이루어지고 마지막에 사용자가 접근하고자 하는 자원에 대해서 승인또는 거부를 판단하게 된다. 사용자가 이 필터까지 지나간다면 서버자원에 접근이 가능하다.
사용자가 요청을 하게 되면 FilterSecurityInterceptor 에서 사용자가 가지고 있는 인증객체가 존재하는지 판단하게된다. 인증객체가 없으면 예외를 발생하고 더이상 인가 처리를 하지 않는다.
이후에는 ExceptionTranslationFilter 가 받아서 현재 사용자가 인증예외를 발생했기 때문에 로그인 창으로 이동하게 한다
인증객체가 널이 아닐경우에는 SecurityMetadataSource 클래스는 현재 사용자가 user라는 url로 접근을 하게 되면 roll_user 접근시 roll_user라는 권한이 필요하다. 그래서 이클래스가 설정된 권한 정보를 가져오고 조회 하는 역할을 한다
user라는 자원에 설정된 권한정보가 null이면 권함심사를 하지 않는다 user자원을 접근하기 위해서는 권한이 필요하지 않고 누구나 접근이 가능하다는 의미다.
user라는 자원에 설정된 권한정보가 null이 아니라면 권한정보를 AccessDecisionManager 에게 전달해주고 이클래스가 권한정보를 참조해서 권한심사를 하게 된다.
내부적으로 AccessDecisionManager는 최종심의 결정자가 되는건데 AccessDecisionVoter 를 통해서 심의요청을 하게된다. 사용자가 자원에 접근하려 할때 최종적으로 접근자격이 있는지 없는지 판단하여 승인/거부 를 AccessDecisionManager리턴하게된다.
AccessDecisionManager리턴받은 결과값으로 최종적으로 사용자가 자원에 접근이 가능한지를 판단하게된다.
접근이 거부 되면 AccessDeniedException 인가예외를 발생하게 되고 ExceptionTranslationFilter 가 받아서 인가예외처리를 하게된다.
필자는 "/user" 권한을 USER 로 설정해줬고 GetMapping("/user")로 설정해줬다 USER 권한을 가진 사용자만 접근이 가능하다
필자는 로그인을 하지 않고 일단 루트 바로 접속이 가능한 home으로 접속 시도를 했다.
FilterChainProxy 에서 가장 먼저 호출된다. 이클래스는 보안 기능을 처리 하는 필터 목록들을 가지고 있는데 확인해보면 14개의 필터를 호출하는걸 확인할수 있다. 마지막에 보면 FilterSecurityInterceptor 바로위에는 ExceptionTranslationFilter(예외처리) 를확인할수 있다.
ExceptionTranslationFilter가 먼저 받게 된다. 이필터는 바로 그다음 필터로 이동하는데 try catch로 감싸서 다음 필터로 이동하게된다.
그다음 필터에서 발생하는 모든예외는 catch문으로 넘어 온다
ExceptionTranslationFilter 와 FilterSecurityInterceptor 는 예외를 받고 예외를 처리하는 필터클래스 라고도 할수 있다.
이후에 FilterSecurityInterceptor필터가 인가처리를 하게 된다. FilterInvocation( request, response ,chain) 객체를 생성해서 전달한다
이후에 부모클래스에게 다시 호출 하고 있다. 부모 클래스를 보면 필터 클래스와 메소드보안 인가처리를 담당하는 클래스가 존재하고 2개다 부모클래스를 상속받고 있다 . MethodSecurityInterceptor는 필터는 아니다 말그대로 Interceptor이고 최상위 클래스는 advice다
이클래스는 인가처리를 할때 AOP 기반으로 동작을 하는 클래스이다.
사용자가 현재 유저라는 자원에 접근하면 유저의 설정된 권한정보를 가져 오는 역할을 한다 ExpressionBasedFilterInvocationSecurityMetadataSource! 필자가 설정한 자원에 해당하는 권한정보를 가져 오고 있다. 현재는 누구나 접근이 가능한 home 으로 요청을 했다 그래서 permitAll 을 확인할수가 있다.
인증객체가 널인지 아닌지 여부를 판단한다 현재는 인증을 하지 않았고 home으로 요청을 했다 그러면 사용자는 어떤 인증객체를 가지고 있을까? 여기 까지 오면서 굉장히 많이 봤던 AnonymousAuthentication(익명사용자) 토큰을 가지고 있는걸 확인할수 있다. 그렇기 때문에 이구문에는 해당하지 않는다 ~ 그러면 풰스~~~ 아맞다! 여기서 만약 널이라면 예외를 발생하고 인가처리를 하지 않는다!!
여기서 인가 처리를 위임하게 되는데 accessDecisionManager의 구현채를 한번 보자!
앞에서 보면 AccessDecisionVoter 가 심의한다고 했다! 즉 여기서 심의을 진행하고 처리 하게 된다. voter 로 들어가보자
이클래스를 보면 승인(ACCESS_ABSTAIN) / 거부 (ACCESS_DENIED)를 통해서 심의결과를 리턴한다
현재 필자는 home로 접근하면 접근이 가능하다
현재 상태에서 user로 접근을 해보자 이클래스를 다시 보면 user정보에 대한 권한정보를 가져오고 있다.
user에 접근하기위해서는 USER라는 권한이 필요하다 현재는 USER 권한을 가지고 있지 않기 때문에 deny을 통해서 접근 거부 결과를 받았다. 그예외를 AbstractSecurityInterceptor에서 받아서 다시 전달한다.
AbstractSecurityInterceptor에서 던져준 예외를 이클래스에 받고 예외 타입이 인증예외 또는 인가예외로 나누어서 처리를 한다 지금은
인가 예외이기때문에 AccessDeniedException이 받게된다. 그리고 현재 사용자는 AnonymousAuthentication(익명사용자) 이기 때문에 sendStartAuthentication구문으로 가게 되고 RememberMe인증을 받지 않았을경우에는 accessDeniedHandler 구문으로 가게 된다.
현재는 AnonymousAuthentication(익명사용자) 이기 때문에 sendStartAuthentication구문으로 가게된다.
최종적으로 loginForm 으로 가게된다.
이제 user계정으로 인증을 받아보자!! 처음에는 거부가 된다 왜냐 아직 인증을 받지 않았기 때문이다. 인증을 받아도 현재 필자는 USER라는 권한을 가지고 있지 않기 때문이다 서버 자원에만 권한설정을 해줬지 user계정에는 아직 권한을 부여하지 않았다 그래서 user로 접근을하게되면 403에러를 맞이하게된다.
여기서 USER라는 권한을 부여 하고 다시 들어가보자 ! 자 필자는 인증과 권한여부를 모두 통과 했다 !
accessDecisionManger가 인가처리를 하게되는데 그사용자가 가진 권한과 자원에 설정된 권한을 조회 하고 최종적으로 voter 에게 심의를 하게 되고 여기서 나온 결과값들을 가지고 예외처리를 할것인지 아니면 인가처리가 될것인지 여부를 판단한다. 현재 필자는 권한 결과갑이 ROLE_USER 로 확인된다.
자 user로 들어왔다 하 여기 까지 오기 멀다 멀어 정말 멀다
'SpringSecurity' 카테고리의 다른 글
SpringSecurity(아키텍처 정리) (0) | 2020.11.11 |
---|---|
SpringSecuirty(AccessDecisionManager,AccessDecisionVoter) (0) | 2020.11.11 |
SpringSecurity(AuthenticationProvider) (0) | 2020.11.09 |
SpringSecurity(AuthenticationManager) (0) | 2020.11.07 |
SpringSecurity(AuthenticationFlow) (0) | 2020.11.05 |