두 손끝의 창조자

웹 애플리케이션에서의 인증 절차와 Spring Security 본문

Spring

웹 애플리케이션에서의 인증 절차와 Spring Security

codinglog 2020. 4. 27. 18:24

일반적인 웹 애플리케이션에 접속해서 인증을 받는 절차를 한번 상상해 보자.

  1. 자원요청 : home 페이지에 접속을 해서 열어보고 싶은 링크를 클릭한다.
  2. 요청자원인식 : 링크를 클릭하면 요청이 서버로가고, 서버는 사용자가 요청한 자원이 보호된 자원이라고 인식한다.
  3. 요청자원 제공 불가 알림 : 사용자가 인증되지 않은 상태라면, 서버는 사용자에게 인증, 즉 로그인을 하라고 알려준다. 이때 로그인 페이지로 이동될 수도 있고 아니면 그냥 에러 페이지를 띄울수 있다.
  4. 인증 인터페이스 : 인증 메커니즘에 따라서 ID와 패스워드를 입력하는 폼이 뜰수고 있고, 브라우저가 BASIC 인증 다이얼로그 박스나, 쿠키나, X.509 인증서 등을 뒤져서 신상을 파악한다.
  5. 인증요청 : 브라우저는 입력된 ID, 패스워드를 서버로 보내던지, HTTP 헤더에 인증정보를 실어서 보내던지 서버로 인증 정보를 보낸다.
  6. 인증처리 : 서버는 받은 인증정보가 유효한지 검사한다. 틀리면 다시 2번 으로 돌아간다.
  7. 자원 재요청 : 원래 요청했던 자원을 브라우저에게 내려준다. 단, 인증된 사용자가 요청한 자원에 대한 권한이 있어야 한다. 권한이 없으면 HTTP의 403 에러코드(권한없음)를 돌려준다.

스프링 시큐리티에는 위의 스텝에 맞는 클래스를 제공하는데 ExceptionTranslationFilter,AuthenticationEntryPoint 클래스와 AuthenticationManager 를 호출하는 인증 메커니즘이다.

ExceptionTranslationFilter

스프링 시큐리티에서 발생시키는 모든 예외를 감지하는 스프링 시큐리티의 필터이다. 일반적으로 AbstractSecurityInterceptor에 의해서 예외가 발생하는데, 이놈은 HTTP나 인증원리에 대해서는 알고있는 것이 없다. 대신에 ExceptionTranslationFilter 가 어떤 예외가 발생했는지, 예들들어 403 에러코드를 리턴해야하는지 AuthenticationEntryPoint를 실행해야하는지 알아서 처리한다.

AuthenticationEntryPoint

위에서 3번째 단계를 담당하고 있는 클래스이다. 주요 인증 시스템에는 그것들만의 AuthenticationEntryPoint의 구현을 가지고 있다.

Authentication Mechanism

브라우저가 ID/PASSWORD 폼을 보내든, HTTP 헤더에 인증정보를 보내든 서버로 정보를 주면 이것들을 모아서 처리하는 것이 필요한데 스프링 시큐리티에서는 이런 일을 하는 것을 인증 메커니즘이라고 한다. 예를들면 -form-base login-, -Basic authentication- 등이 있다. 인증 상세 정보가 모아지면 Authentication 오브젝트를 생성하고 AuthenticationManager에 넘긴다.

인증 메커니즘이 인증처리에 성공을 하면 Authentication 오브젝트는 완전체로 되고 인증이 유효한것으로 인식한다. 이어서 SecurityContextHolderAuthentication를 넣고 위의 7번 단계를 수행한다.

요청간 인증정보 공유

애플리케이션 종류에 따라서 다르겠지만 인증 정보를 저장하는 전략이 필요하다. 일반적인 웹 애플리케이션은 한번 로그인을 하면 인증 정보를 세션ID로 구분한다. 스프링 시큐리티는 SecurityContextPersistenceFilter로 인증정보를 저장하고 불러온다. 요청마다 SecurityContextHolder로 복원하고 요청이 완료되면 SecurityContextHolder를 지운다. 인증정보에 접근하기 위해서 HttpSession에 직접 접근해서 무언가 하는 것은 위험할 수 있으니 안하는 것을 추천한다.

무상태 RESTfull web service 같은 것은 HTTP 세션을 사용하지 않고 요청마다 인증처리를 한다. 그렇다 하더라도 요청에 대한 처리가 끝나면 SecurityContextHolder가 지워지도록 SecurityContextPersistenceFilter 을 사용해야 한다.

반응형
Comments