사용자를 인증하는데, 사용자는 세션 고정 공격(session fixation attack)을 막기 위해 새로운 세션 아이디와 연동된다.
Example 3. 인증된 사용자가 새로운 세션과 연동됨(Authenticated User is Associated to New Session)
HTTP/1.1 302 Found Location: / Set-Cookie: SESSION=4c66e474-3f5a-43ed-8e48-cc1d8cb1d1c8; Path=/; HttpOnly; SameSite=Lax
연속적인 요청은 session cookie를 포함하는데, 이것은 session의 나머지 사용자를 인증하기 위해 사용된다.
Example 4. Credentials로 제공된 인증받은 세션(Authenticated Session Provided as Credentials)
GET / HTTP/1.1 Host: example.com Cookie: SESSION=4c66e474-3f5a-43ed-8e48-cc1d8cb1d1c8
여기서 이러고 SecurityContextRepository에 대해 바로 설명을 하는데, (왜케 불친절? ㅠㅠ)
내 생각에는 이렇게 로그인을 한 후 세션 정보, 쿠키 정보 같은 것을 우리가 SecurityContext에 사용자 인증(authentication)정보를 저장하는데, 이것을 SecurityContextRepository의 구현체를 통해 읽고 다시 사용자 정보를 저장하고 하는 것 같다.
그래서 이후에 SecurityContextRespository와 연관된 class가 설명되는 것 같다.
SecurityContextRepository
Spring Security에서 미래 요청에 대한 사용자와의 연관은 SecurityContextRepository를 사용해서 생성된다.
여기서 SecurityContextRepository가 무슨 역할을 하는지 물어본다면? 공식문서에는 아쉽게도 이에 대해 설명을 자세히 해놓지는 않았다.
그래서 필자 키메라는 apidoc에서 이에 대한 정보를 찾고자 했다. SecurityContextRepository가 정확히 어떤 친구(절교하자)인지 궁금다옹...
SecurityContextRepository는 SecurityContext를 요청들 사이에서 저장하기 위해 사용되는 전략이다.
SecurityContextRepository는 3가지 메소드 loadContext, saveContext, containsContext로 구성되어 있다.
loadContext
뭔가 이름 그대로 저장된 context를 불러올거 같은 느낌인데...
공급된 요청으로부터 security context를 얻는다고 한다. (진짜네 ㅎㅎ...)
saveContext
요청의 완료에서 security context를 저장한다.
containsContext
현재 요청을 위한 security context를 포함하고 있는지 아닌지를 repository가 확인하도록한다.
SecurityContextRepository의 기본 구현체는 HttpSession을 SecurityContext와 연관시키는HttpSessionSecurityContextRepository다. 사용자는 HttpSessionSecurityContextRepository를 SecuriyContextRepositorty의 다른 구현체로 대체가 가능하다.
스프링 시큐리티는 기본적으로 HttpSessionSecurityContextRepository 를 사용하기 때문에 인증정보가 HttpSession 에 저장된다.
그런데 만약 동시접속자 수가 많은 서비스라면 세션에 인증정보를 저장하는 것은 서버에 부담을 주게 된다. 따라서 그런 경우 인증정보를 암호화하여 쿠키에 저장하거나(물론 복호화되지 않는 암호화 알고리즘을 사용하더라도 개인정보가 쿠키에 저장되는 일은 없어야 한다.)
, Redis 와 같은 cache 서버를 사용해야 하는데 그러려면 SecurityContextRepository 를 implement 하여 새로운 SecurityContextRepository 를 정의해야 한다.
만약 HttpSession와 SecurityContex를 연관시킬 필요가 없다면, NullSecurityContextRepository가 SecurityContextRepository의 구현체다.
RequestAttributeSecurityContextRepository
RequestAttributeSecurityContextRepository는 요청 속성으로서 SecurityContext를 저장하는데, SecurityContext가 지울 수 도 있는 dispatch type들 사이에서 발생하는 하나의 요청에도 사용할 수 있다는 것을 확실히 한다.
(무슨 말이야...? ㅠㅠ)
예를 들어, client가 만든 요청이 인증되었고 에러가 발생한다고 가정하자. servlet container 구현체에 의존해서, 에러는 생성된 SecurityContext가 지워지고 그리고 나서 error dispatch가 만들어졌다는 걸 의미한다.
error dispatch가 만들어지면, SecuriyContext는 없는데, 이것은 error page가 인증 혹은 현재 사용자를 보여주기 위해 SecurityContext를 사용할 수 없다는 것이다. SecurityCOntext가 다소 지속되지 않는다면 말이다.
Example 5. Use RequestAttributeSecurityContextRepository
SecurityContextPersistenceFilter는 요청들 사이에서 SecurityContextRepository를 사용해서 SecurityContext를 지속시키는데 책임이 있다.
1. 애플리케이션을 작동시키기 전에, SecurityContextPersistenceFilter가 SecurityContextRepository로 부터 SecurityContext를 담고 SecurityContextHolder에 그것을 세팅한다.
지난 글에서 Architecture에 대해 공부할 때 SecurityContextHolder에 대해 알아본 적 있다.
SecurityContext사용자의 로그인 정보를 가지고 있는데, 이것을 또 가지고 있는 곳이 SecurityContextHolder라고 했다.
그런데 이제보니 SecurityContextPersistenenceFilter에서 SecurityContextRespository를 이용해서 이 정보를 담아준거네!
2. 다음으로, 어플리케이션이 작동한다.
3. 마지막으로, SecurityContext가 변했다면, 우리는 SecurityContext를 SecurityContextPersistenceRepsitory를 사용해서 저장한다. SecurityContextPersistenceFilter를 사용할 때 SecurityContextHolder를 세팅하는것은 SecurityContext가 SecurityContextRepository사용하는것을 지속할 수 있다는 말이다.
3. SecurityContextHolderFilter
SecurityContextHolderFilter는 SecuriyContextRepository를 사용하는 요청들 사이에서 SecurityContext를 불러오는데 책 임이 있다.