본문 바로가기
Auth (Authentication & Authorization)

Spring-Security Authentication Structure

by kellis 2020. 10. 12.

Spring-security는 많은 Filter의 chain으로 구성되어 있습니다. 따라서 요청이 들어오면 Authentication/Authorization을 위해 일련의 Filter를 거치게 됩니다. 사용자 인증 요청 시에는 인증 모델을 기반으로 적합한 Filter를 찾을 때까지 Filter chain을 통과합니다. 

 

이 포스트에서는 UsernamePasswordAuthenticationFilter에 도달할 때까지 Filter chain을 통과하도록 코드를 작성할 것입니다. 

 

UsernamePasswordAuthenticationFilter를 AuthenticationFilter라고 칭할 것이며 이 Filter의 동작 방식을 그림과 함께 살펴보겠습니다.

 

[request with invalid session] : 인증하기 전, 인증이 필요한 화면에 요청 

1. Spring-security를 이용하면 모든 요청은 Session을 발급받습니다. (Session을 발급받으면 클라이언트의 쿠키에 JSESSIONID라는 키로 SessionID가 저장됩니다) AuthenticationFilter는 해당 요청의 JSESSIONID(SessionID)를 확인하여 JSESSIONID와 매핑되는 인증 정보(Authentication)가 Security Context에 있는지 판단합니다. JSESSIONID(SessionID)에 매핑되는 Authentication이 Security Context 내에 없으므로 LoginPage로 이동시킵니다. 

 

[request for authentication with username/password] : 로그인 양식으로 인증을 요청

2. AuthenticationFilter는 기본적으로 로그인 폼으로부터 오는 데이터를 username과 password로 인식하고 있습니다. 따라서 로그인 폼의 input name도 username/password로 맞춰줘야 합니다. 

 

<form action="/login" method="post">
        <input type="text" id="username" name="username"/>
        <input type="password" id="password" name="password"/>
        <button type="submit">Log in</button>
</form>
  • 1라인 : action을 "/login"으로 입력했는데, 이것 역시 Spring-security가 default로 설정한 MappingURL입니다. 따라서 action을 맘대로 바꿔버리면 Spring-security의 인증 요청으로 받아들여지지 않습니다. 

 

AuthenticationFilter는 입력받은 username, password를 이용해 UsernamePasswordAuthenticationToken을 만듭니다. 이 클래스는 Authentication 인터페이스의 구현체입니다. 이것을 AuthenticationToken이라고 통칭하겠습니다. 그리고 AuthenticationToken에 있는 username, password가 유효한 계정인지 판단하기 위해 AuthenticationManager에게 위임합니다. 

 

3. AuthenticationManager는 기 등록한 AuthenticationProvider들을 연쇄적으로 실행시킵니다. AuthenticationProvider의 구현체에서는 다음과 같은 작업이 필요합니다. 

  1) AuthenticationToken에 있는 계정 정보가 유효한지 판단하는 로직 (DB로부터 조회)

  2) 계정 정보가 유효하다면 유저의 상세 정보(이름, 나이 등 필요한 정보)를 이용해 새로운 UserPasswordAuthenticationToken을 발급 

 

4, 5. 새롭게 발급받은 AuthenticationToken을 Security Context에 저장합니다. 

 

이 그림에는 포함되어있지 않지만, 계정 정보가 유효하다면 AuthenticationFilter는 AuthenticationSuccessHandler에 따라 요청을 redirect시킵니다.

 

[request with valid sessionId] : 인증 후, 인증이 필요한 화면에 요청 

6. AuthenticationFilter가 해당 요청의 JSESSIONID(SessionID)와 매핑되는 AuthenticationToken이 있는지 판단합니다. 존재하면 해당하는 AuthenticationToken을 반환받아 이후 요청 흐름에 포함시킵니다. 따라서 Controller, Service, jsp에서 이 AuthenticationToken 정보를 사용할 수 있습니다. 

(Spring MVC Lifecycle에서 알 수 있듯이, 요청은 Filter chain을 통과 후 DispatcherServlet에 의해 전달됩니다)

댓글