Spring

Spring Security 6 - Authentication Persistence and Session Management

ppusda 2024. 6. 22. 19:10

Notion - Spring Security 6 - Authentication Persistence and Session Management

 

이 글에서는 Spring Security 5와 6의 인증 영속성, 세션 관리에 대한 차이점과 트러블 슈팅을 진행하며 자세히 정리하기 애매했던 내용을 작성해보려고 한다.

아래 내용을 참고하여 작성하였다.

Authentication Persistence and Session Management :: Spring Security

 

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

 

Persisting Authentication :: Spring Security

 

Persisting Authentication :: Spring Security

The first time a user requests a protected resource, they are prompted for credentials. One of the most common ways to prompt for credentials is to redirect the user to a log in page. A summarized HTTP exchange for an unauthenticated user requesting a prot

docs.spring.io

 

기본 Filter 구성 변경

Spring Security 6에서는 SecurityContextPersistenceFilterSessionManagementFilter가 기본적으로 설정되지 않도록 변경되었다.

SecurityContextHolderFilter 를 기본 동작으로 선택하게 되었다.

또한, SecurityContextHolderFilter 또는 SecurityContextPersistenceFilter 중 하나만 설정되어야 하며, 두 필터가 동시에 설정되어서는 안된다.

SecurityContextRepository의 명시적 저장

Spring Security 5

Spring Security 5에서는 SecurityContextPersistenceFilter를 사용하여 자동으로 SecurityContext를 SecurityContextRepository에 저장하는 것이 기본 동작이었다.

 

SecurityContextPersistenceFilter 는 SecurityContextRepository을 통해서 요청을 처리하기 전에 복원하는 작업과 응답을 반환하기 전에 SecurityContext에 변경사항이 있다면 자동으로 저장하는 작업을 진행한다.

이 과정에서 불필요한 상황에서도 Session에 SecurityContext를 저장하는 상황이 발생하기도 하며, 요청이 완료되기 전에 SecurityContext의 상태가 변하게 됬을 때 예상치 못한 결과를 가져올 수도 있었다는 문제가 있었다.

 

Spring Security 6

이러한 문제점을 개선하기 위해 Spring Security 6 부터는 SecurityContextPersistenceFilter를 대체하여 SecurityContextHolderFilter를 기본 동작으로 사용하게 되었다.

 

SecurityContextHolderFilter도 SecurityContextRepository를 통해서 복원하는 작업을 진행하기는 하지만, 자동으로 저장하는 작업은 진행하지 않는다.

만약 SecurityContext를 저장하는 작업을 진행하고 싶다면, requireExplicitSave(true) ****를 통해 설정하여 명시적으로 저장해야만 한다.

 

정리

동작 방식 SecurityContextPersistenceFilter SecurityContextHolderFilter
SecurityContext 로드 및 저장 요청 처리 전에 SecurityContext를 로드하고, 응답 반환 전에 변경된 경우 SecurityContext를 저장함. 요청 처리 전에만 SecurityContext를 로드하고 저장하지 않음.
자동 저장 여부 이 필터를 사용하면 SecurityContext가 자동으로 저장됨. 변경된 경우 응답 반환 전에 SecurityContext가 저장됨. 이 필터를 사용하는 경우 SecurityContext는 자동으로 저장되지 않음. 명시적으로 저장해야 함.
응답 처리 방식 응답이 클라이언트로 커밋되고 기록되기 전에 SecurityContext 변경 여부를 감지하고, 변경된 경우 응답 커밋 전에 저장함. 응답 처리에 관여하지 않고, 오로지 SecurityContext를 로드하는 데만 사용됨.
복잡성 HttpServletRequest 및 HttpServletResponse를 감싸어야 하므로 구현이 복잡함. SecurityContext를 로드하는 역할만을 수행하므로 구현이 비교적 간단함.

SessionManagementFilter 구성

SessionManagementFilter

SessionManagementFilter는 현재 요청 동안 사용자가 인증되었는지 확인하기 위해 사용된다.

그 과정에서 SecurityContextRepository의 내용과 SecurityContextHolder의 현재 내용을 확인하여 SecurityContext에 Authentication 객체가 포함되어 있는지 확인하고 인증 여부를 확인한다.

사용자가 인증되었음을 확인한 이후 SessionAuthenticationStrategy를 호출하여 세션 보호를 활성화하거나 동시 로그인을 확인하는 등의 작업을 진행한다.

 

Spring Security 5

Spring Security 5에서는 기본 설정인 SecurityContextPersistenceFilter 에서 필요에 따라 SessionManagementFilter를 통해 세션을 관리한다.

이는 위에서 설명했다시피 사용자가 방금 인증되었는지 감지하고 SessionAuthenticationStrategy를 호출한다.

하지만 이는 모든 요청에 대해 HttpSession을 읽어야 한다는 문제가 있다.

 

Spring Security 6

Spring Security 6에서는 인증 매커니즘이 자체적으로 SessionAuthenticationStrategy를 호출해야 하도록 변경되었다.

이는 인증이 완료되었는지 감지할 필요가 없으므로 모든 요청에 대해 HttpSession이 읽힐 필요가 없어진다.

 

SessionManagementFilter를 사용할 때 고려해야 할 점

Spring Security 6부터는 기본적으로 SessionManagementFilter가 사용되지 않는다.

그렇기에 sessionManagement의 일부 메서드는 예외를 발생시키거나 아무런 동작을 하지 않을 것이다.

AuthenticationFailureHandler 를 통해 인증 매커니즘 내에 구현하거나 SessionAuthenticationStrategy를 설정하는 방법을 꼭 사용해햐 함을 유의하자.

Method Replacement
sessionAuthenticationErrorUrl AuthenticationFailureHandler 를 인증 로직 내에 설정해야 함.
sessionAuthenticationFailureHandler AuthenticationFailureHandler 를 인증 로직 내에 설정해야 함.
sessionAuthenticationStrategy 논의된 세션 생성 정책을 SessionAuthenticationStrategy 를 인증 로직 내에 설정해야 함.