JAVA(SPRINGBOOT)

[SPRING SECURITY] 시큐리티 파헤치기 (4) - AUTHENTICATION

본듀 2023. 3. 23. 14:19

DaoAuthenticationProvider

로그인시 username과 password를 제출하면
UsernamePasswordAuthenticationFilter가

Authentication 타입의 UsernamePasswordAuthenticationToken을 만들어
AuthenticationManager에게 전달되고,
DaoAuthenticationProvider에게 전달된다.

DaoAuthenticationProvider는
token의 username을 이용해 UserDetailsService에게 Userdetails을 요청받고,
PasswordEncoder를 통해 UserDetails의 password와 token의 password를 비교한다.

인증에 성공하면 UsernamePasswordAuthenticationToken 타입의 Authentication이 반환되고,
이 정보는 authentication Filter에 의해 SecurityContextHolder에 저장된다.

 

UserDetailsService

DaoAuthenticationProvider가 인증에 관련된 정보를 얻기위해 사용한다.

 

UserDetails

UserDetailsService의 반환타입이며,
이를 통해 DaoAuthenticationProvider는 검증을 하고
Authentication의 principle에 UserDetails를 저장한다.

이 때까지 UserDetailsService, UserDetails만 Custom해서 사용했는데
DaoAuthenticationProvieder에서 사용된다는 것을 알 수 있었다.

postman으로  url-encoded 설정을 안하고 폼로그인 테스트를 할 때,
DaoAuthenticationProvider에서 username이 null이라 error가 생긴적이 있는데
어떤 과정에서 error가 생겼는지 이해할 수 있게 되었다.

 


 

Persistence

SecurityContextRepository

SpringSecurity에서는 SecurityContextRepository를 통해 사용자와 향후 요청이 연결된다.
구현체는 일반적으로 DelegatingSecurityContextRepository이며,
HttpSessionSecurityContextRepository (세션에 SecurityContext 저장)
RequestAttributeSecurityContextRepository (request의 attribute에 SecurityContext 저장)
에 위임한다.

 

DelegatingSecurityContextRepository

SecurityContext를 여러 SecurityContextRepository에 저장하고, 일련의 순서로 검색할 수 있다.

 

SecurityContextPersistenceFilter

SecurityContextRepository를 이용해 여러 request간에 SecurityContext가 유지될 수 있도록한다.

1. SecurityContextPersistenceFilter에 들어오면 어플리케이션을 실행하기전
    SecurityContextRepository에 저장된 SecurityContext를 SecurityContextHolder에 로드한다.
2. 그 후, 요청들을 처리한다.
3. SecurityContext가 수정되면 SecurityContextRepository에 저장한다.

SecurityContextPersistenceFilter의 메서드가 완료되기 전 redirect가 되는 등 response가 commit되면
이미 작성된 response에 sessionId가 없기 때문에 session을 생성하지 못한다.

이런 문제를 해결하기 위해 SecurityContextPersistenceFilter는
SecurityContext의 변화를 감지, 저장을 목적으로 request와 response를 감싸고있다.

 

SecurityContextHolderFilter

SecurityContextRepository를 이용해 여러 request간에 SecurityContext를 로드할 수 있도록 한다.

SecurityContextPersistenceFilter와는 다르게 
SecurityContextRepository로부터 SecurityContext를 SecurityContextHolder에 저장만하고,
수정된 SecurityContext를 SecurityContextRepository에 저장하지 않는다.

그렇기 때문에 명시적으로 SeurityContext를 저장해야한다.

여러 요청들간에 인증처리된 SecurityContext를 관리하기 위해 
SecurityContextRepository가 사용되는데

SecurityContextPersistenceFilter는 Repo로부터 Context 불러오고 저장하지만,
SecurityContextHolderFilter는 불러오기만 한다.

SecurityContextPersistenceFilter 내 메서드가 완료되기전 response가 커밋되면
잘못된 세션 ID를 가지고 요청이 가 문제를 일으킬 수 있기 때문에 
SecurityContextHolderFilter를 사용해 불러오기만 하고 명시적으로 Context를 저장해주도록
바뀐 것으로 보인다.

그리고 Filter가 기본적으로 읽기 기능만 있으면 되기 때문에 퍼포먼스가 향상된다.

 

 

Session Management

인증 처리를 하는 어플리케이션에서
인증된 Authentication을 향후 요청을 위해 어떻게 유지하고, 복구할지 고려해봐야한다.

기본값으로 자동 처리되게 설계되어있지만, 
HttpSecurity에서 requireExplicitSave의 의미를 이해하는 것이 중요하다.

Spring Security 6에서는 
SecurityContextPersistenceFilter와 SessionManagementFilter는 기본값이 아니며,
SecurityContextHolderFilter와 SecurityContextPersistenceFilter는 둘 중에 하나만 존재해야한다.

 

SessionManagementFilter

SessionManagementeFilter는 유저가 현재 요청 중 인증을 받았는지 결정하기 위해
SecurityContextRepository와 SecurityContextHolder를 비교한다.

Repository가 SecurityContext를 가지고 있다면 Filter는 아무 일도 하지 않는다.
그렇지 않거나, thread-local SecurityContext가 Authentication을 포함하고 있다면
Filter는 이전에 인증을 받았다고 가정하고 SessionAuthenticationStrategy를 호출한다.
만약 유저가 현재 인증되지 않았다면 부적절한 sessionId가 요청되었는지 호가인하고
InvalidSessionStrategy를 호출한다.

 

Moving Away from SessionManagementFilter

SpringSecurity5에서는 
기본적으로 유저가 인증되었는지 확인하고, SessionAuthenticationStrategy를 호출하기 위해
SessionManagementFilter에 의존했다.
이 부분은 매 요청마다 HttpSession을 읽어야한다는 문제점이 있었다.

SpringSecurity6에서 
기본값은 인증 매커니즘자체에서 SessionAuthenticationStrategy를 호출하여
인증이 완료되었는지 확인할 필요가 없어졌고,
매 요청마다 HttpSession을 읽을 필요가 없어졌다.

최근 버전의 Spring Security에서는
SessionAuthenticationStrategy호출을 인증 매커니즘에 포함시킴으로써
인증을 할 때만 SessionAuthenticationStrategy을 호출하고,
인증이 완료된 요청에 대해서는
SessionManagementFilter에서 매번 Session을 불러와 확인하던 절차를
없앰으로써 효율적인 방향을 나아가는 것으로 이해했다.

 

그 외의
Custonmizing Where the Authentication Is Stored,
Storing the Authentication manually 등의
Session관리를 위한 설정에 대한 매뉴얼은 공식홈페이지를 참고하면 좋을 것 같다.
https://docs.spring.io/spring-security/reference/servlet/authentication/session-management.html

 

Authentication Persistence and Session Management :: Spring Security

Session fixation attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a p

docs.spring.io

 

 

'JAVA(SPRINGBOOT)' 카테고리의 다른 글

[SPRING SECURITY] 시큐리티 파헤치기 (3) - AUTHENTICATION  (0) 2023.03.22
[SPRING SECURITY] 시큐리티 파헤치기 (1)  (0) 2023.03.16
[JPA] PAGEABLE  (0) 2023.03.13
[SPRINGBOOT] 좋아요 수 표현  (0) 2023.03.09
[JAVA] VECTOR  (0) 2023.01.26