2023년 1월 1일
08:00 AM
Buffering ...

최근 글 👑

3장 스프링 시큐리티 세션 제어 , 세션 고정 보호 , 세션 정책

2023. 12. 24. 22:46ㆍ스프링 시큐리티 -세션/Chatper01 스프링 시큐리티 전반적인 기능

 

 

 

 

 

[동시 세션 제어]

 

스프링 시큐리티를 사용하다보면 세션은 유저의 인증인가 역활에 큰 역활을 한다.

하지만 이런경우 생각해보자.

 

 

1. 내 아이디를 다른 사람이 들어와서 세션을 발급받은 경우

 

만약 내가 쓰는 아이디가 있고 , 이 아이디를 현재 사용하고 있다.

하지만 내 아이디랑 비밀번호가 누군가에게 탈취당해서

 

내가 지금 해당 웹사이트를 사용하고 있는 와중에 누군가가 내 아이디로 인증을 받고

세션을 받아서 해당 웹사이트로 들어오게 되었다.

 

그럴경우 어떤식으로 이 방법을 해결할지가 동시 세션제어이다.

 

 

 

1. 만약 동시 세션이 들어왔다면 두 가지 해결방안이 있다.

 

1.이전 사용자 세션만료

 

만약에 user라는 아이디로 총 2명의 클라이언트가 들어왔다.

user : member1 

user : member2 이렇게 가정을 해보자.

 

이럴 경우 세션이 동시에 두 개가 발급이 되었고 같은 아이디로 내 사이트에 접속중이다.

이럴 경우 이전 사용자를 세션을 만료 시키는 방식이 있다.

 

이 방식을 사용하면 user : member1

즉 제일 먼저 들어온 사용자의 세션을 만료 시켜 버리는 것 이다.

 

그렇게 된다면 member1의 세션은 만료가 되고 다시 인증이 필요한 사이트를 들어갈 때

인증을 받지 못하고 login페이지로 가게 될 것 이다.

 

이것이 이전 사용자 세션만료 방식이다.

 

 

2. 현재 사용자 인증 실패

 

아까 위에 처럼 내 아이디로 동시에 두명의 클라이언트가 들어왔다.

 

user : member1

user : member2

 

첫 번째 방식은 기존의 있는 사용자의 세션을 만료 시켜버리고

새 사용자의 세션을 유지시키는 방식을 사용하고 있는 반면에

 

두 번째 방식은 기존의 있는 사용자의 세션을 유지시키되

새 사용자는 같은 아이디로 들어올 수 없게 하는 것 이다.

 

메이플스토리를 한번 생각해보자.

 

 

 

 

마치 이러한 경우와 흡사하다고 생각하면된다.

 

기존 유저는 로그인이 되어있고

새 사용자가 들어올 때 새 사용자의 접근권한을 막아버리는 것 이다.

 

 

 

 

즉 이런식으로 새 사용자의 접근 권한을 막아 버린다.

 

어떠한 전략방식을 사용할지는 개발자의 판단에 따라 다르다.

 

그렇다면 어떤식으로 사용하는지 보도록 하자.

 

 

 

 

 

해당 api를 살펴보면 다음과 같다.

 

sessionManagement

 

Session의 방식을 설정 할 수 있게 해주는 메서드이다.

기본적으로 이 세션매니저 안에서 세션의 상태를 설정 할 수 있다.

 

maximumSessions()

 

 

세션의 갯수를 설정하는 것 이다.

 

만약 1이라고 한다면 아이디마다 세션은 1개씩 발급이된다.

 

하지만 user라는 아이디에 2명의 사용자(클라이언트)가 들어왔을 때는 세션은 2개가 발급이된다.

그럴 경우 세션의 갯수는 1개로 설정을 하였기 때문에 오류가 나게된다.

 

즉 한 아이디에 세션의 갯수를 몇개로 설정을 해놓을 것 인지 설정하는 메서드이다.

기본적으로는 1개를 설정해놓는다.

 

만약 한 계정에 세션을 무한대로 하고싶다면 -1로 설정하면 세션의 갯수는 무한대가 된다.

 

 

maximumSessions(1).maxSessionsPreventsLogin(true)

 

maxSessionPreventsLogin은 maximumSessios와 같이 사용하는 메서드이며

 

앞서 위에 설명했다 싶이 동시의 두명의 사용자가 들어왔을때 상태전략이다.

1. 이전 사용자의 세션을 만료할 것

2. 새 사용자의 접근권한을 막아버린다.

 

이 두가지의 상태전략을 가지고 있으며

 

maxSessionPreventsLogin에는 bool타입이 들어간다.

 

true일 경우 = 새 사용자(후속 사용자)가 동일 아이디로 들어올 때 오류를 터뜨림.

false일 경우 = 이전 사용자의 세션을 만료시켜서 접근권한을 없애버림

 

 

.invalidSessionUrl("/home")

 

invalidSessionUrl의 경우 세션이 유효하지 않을 때  어디로 리다이렉트 시킬 지 정하는 메서드이다.

즉 인증권한이 없을 때 해당 사용자를 설정한 url로 리다이렉트 시킨다.

 

 

expiredUrl("/home")

 

 

세션이 만료되었을 경우 설정할 메서드이다.

해당 사용자의 세션이 만료되었을 경우 설정한 url로 보낸다.

 

 

 

[세션 고정 공격]

 

그렇다면 우리는 세션 동시성 제어를 알아봤다.

그렇다면 세션 고정 보호는 무엇일까?

 

세션 고정 공격은 사용자가 있고 공격자가 있다고 하자.

 

만약 사용자가 어떤 웹사이트에 로그인을 했다.
userId : hi
password : 1234

로 로그인을 하였고

세션은 1234로 발급되었다.

 

하지만 어떤 공격자가 이 세션을 탈취해서 해당 세션을 해당 사용자마냥 사용할 수 있다.

이러한 방어정책으로 세션 고정 보호 정책이 있는데

 

세션 고정 보호 정책이란

 

기존의 세션의 id를 로그인을 할 때 마다 새로운 세션 id로 바꾸거나

새로운 세션을 발급해서 추정 할 수 없도록 하거나 탈취 당해도

해당 세션을 파기시키게끔 할 수 있는 정책이다.

 

  

 

 

 

그림으로 본다면 이런 느낌이다.

 

스프링 시큐리티에선 이런 세션 고정보호를 하기위해 기본적으로 설정이 되어있다.

 

 

 

 

해당 메서드를 보자면 이렇다.

 

 

sessionFixation().changeSessionId(

 

기존 세션에 있는 id를 바꿔 추정할 수 없도록 하는 메서드이다.

sessionFixation().none()

 

none으로 설정하게 된다면 해당 세션 보호정책을 끈다.

 

security.sessionManagement(manager -> manager.sessionFixation().newSession());

 

newSession은 로그인 시 기존에 있던 세션을 파기하고

새로운 세션으로 만들어서 발급한다.

 

 

 

[세션 정책]

 

그렇다면 세션정책은 무엇일까?

 

개발할때 세션이 필요할수도 있고 없을 경우도 있다.

예를들어 내가 만약 JWT 토큰을 사용한다면

세션을 사용하지 않음으로 세션은 필요가 없다.

 

즉 세션을 끄거나 킬 수 있는 전략이다.

 

 

 

 

 

security.sessionManagement(sessionConfig ->
        sessionConfig.sessionCreationPolicy(SessionCreationPolicy.ALWAYS));

 

 

세션의 기능을 항상 사용한다.

 

 

security.sessionManagement(sessionConfig ->
        sessionConfig.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));

 

 

스프링 시큐리티가 세션을 필요 시 생성한다 

이 설정은 스프링 시큐리티의 기본값으로 되어있다.

 

 

security.sessionManagement(sessionConfig ->
        sessionConfig.sessionCreationPolicy(SessionCreationPolicy.NEVER));

 

 

스프링 시큐리티가 더 이상 세션을 만들지 않는다.

하지만 세션이 있는 경우 그 세션은 사용한다.

 

 

security.sessionManagement(sessionConfig ->
        sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

 

 

세션을 만들지도 세션이 남아있어도 세션을 사용하지 않는다.

기본적으로 이러한 옵션은 토큰 방식의 인증 기반일 때 사용한다 ( 예 JWT 토큰)