티스토리 뷰
인증 API - 동시 세션 제어
동시 세션 제어란?
동일한 계정으로 인증을 받을 때 생성되는 세션의 허용 개수가 초과되는 경우에 어떻게 세션을 유지하는 것에 대한 제어를 말한다.
최대 세션 허용 개수가 1개라고 가정
(1) 이전 사용자 세션 만료
- 사용자 1이 로그인하고 서버에서 인증 성공 세션 생성
- 사용자 2가 로그인하면 이전 사용자였던 사용자1의 세션을 만료시킴
(2) 현재 사용자 인증 실패
- 사용자 1이 로그인하고 서버에서 인증 성공 세션 생성
- 사용자 2가 로그인 하려고하면 인증 예외가 발생
@Override
protected void configure(HttpSecurity http) throws Exception {
//동시 세션 제어
http
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(false)
.invalidSessionUrl("/invalid")
.expiredUrl("/expired")
}
invalidSessionUrl과 expiredUrl 두 가지를 다 설정했을 경우에는 invalidSessionUrl이 우선순위를 갖는다.
인증 API - 세션 고정 보호
상황 설명
(1) 공격자가 웹 어플리케이션에 접속해서 JSESSIONID를 받음
(2) 사용자는 공격자의 세션쿠키를 사용해서 로그인 시도
(3) 웹 어플리케이션은 JSESSIONID 쿠키가 있으므로 인증 성공
(4) 공격자가 JSESSIONID 쿠키 값이 인증이 되어있기 때문에 사용자 정보를 공유받을 수 있다.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement() //세션 관리 기능이 작동
.sessionFixation()
.changeSessionId(); //서블릿 3.1에서는 기본 값
}
changeSessionId가 기본 값으로 설정된다. SessionManagementConfigure에 있는 내부 클래스 SessionFixationConfigurer에 정의되어있음.
public final class SessionFixationConfigurer {
/**
* Specifies that a new session should be created, but the session attributes from
* the original {@link HttpSession} should not be retained.
* @return the {@link SessionManagementConfigurer} for further customizations
*/
public SessionManagementConfigurer<H> newSession() {
SessionFixationProtectionStrategy sessionFixationProtectionStrategy = new SessionFixationProtectionStrategy();
sessionFixationProtectionStrategy.setMigrateSessionAttributes(false);
setSessionFixationAuthenticationStrategy(sessionFixationProtectionStrategy);
return SessionManagementConfigurer.this;
}
/**
* Specifies that a new session should be created and the session attributes from
* the original {@link HttpSession} should be retained.
* @return the {@link SessionManagementConfigurer} for further customizations
*/
public SessionManagementConfigurer<H> migrateSession() {
setSessionFixationAuthenticationStrategy(new SessionFixationProtectionStrategy());
return SessionManagementConfigurer.this;
}
/**
* Specifies that the Servlet container-provided session fixation protection
* should be used. When a session authenticates, the Servlet method
* {@code HttpServletRequest#changeSessionId()} is called to change the session ID
* and retain all session attributes.
* @return the {@link SessionManagementConfigurer} for further customizations
*/
public SessionManagementConfigurer<H> changeSessionId() {
setSessionFixationAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy());
return SessionManagementConfigurer.this;
}
/**
* Specifies that no session fixation protection should be enabled. This may be
* useful when utilizing other mechanisms for protecting against session fixation.
* For example, if application container session fixation protection is already in
* use. Otherwise, this option is not recommended.
* @return the {@link SessionManagementConfigurer} for further customizations
*/
public SessionManagementConfigurer<H> none() {
setSessionFixationAuthenticationStrategy(new NullAuthenticatedSessionStrategy());
return SessionManagementConfigurer.this;
}
}
인증 API - 세션 정책
설정
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement() //세션 관리 기능이 작동
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}
ALWAYS: 스프링 시큐리티가 항상 세션 생성
IF_Required: 스프링 시큐리티가 필요 시 생성(기본 값)
Never: 스프링 시큐리티가 생성하지 않지만 이미 존재하면 사용
Stateless: 스프링 시큐리티가 생성하지 않고 존재해도 사용하지 않음.
Stateless 설정이 세션, 쿠키로 인증을 하는 방식이 아니라 다른 인증을 사용할 때 사용한다. 예를 들어 jwt 토큰
/**
* Specifies the various session creation policies for Spring Security.
*
* @author Luke Taylor
* @since 3.1
*/
public enum SessionCreationPolicy {
/**
* Always create an {@link HttpSession}
*/
ALWAYS,
/**
* Spring Security will never create an {@link HttpSession}, but will use the
* {@link HttpSession} if it already exists
*/
NEVER,
/**
* Spring Security will only create an {@link HttpSession} if required
*/
IF_REQUIRED,
/**
* Spring Security will never create an {@link HttpSession} and it will never use it
* to obtain the {@link SecurityContext}
*/
STATELESS
}
Q&A
Q. 세션, 쿠키가 생성되는 조건은 로그인 같은 이벤트를 통해 인증 절차를 받아야 사용자 세션이 생기고 세션ID를 클라이너트 쿠키에 담아주는 것 아닌가요?
세션ID 는 클라이언트가 서버에 접속하게 되면 세션쿠키 형태로 발급이 됩니다.
서블릿에서는 JSESSIONID 로 생성합니다.
일반적으로 세션 ID 는 인증과는 무관합니다.
인증은 세션 ID 를 가진 사용자가 본인이 맞는지를 검증하는 단계이지 서버가 인증유무에 따라 세션 ID 를 발급하는 것은 아닙니다.
서버에서는 클라이언트에서 가지고 온 세션 ID 를 기준으로 해서 세션영역에 저장된 여러가지 속성들을 관리합니다.
거기에 로그인 관련된 정보도 포함됩니다.
한가지 기억하실 점은 세션 ID 는 웹 환경일 경우에는 WAS 가 생성을 합니다.
스프링 시큐리티가 직접 생성을 하지 않더라고 WAS 단에서 먼저 생성을 하기 때문에 브라우저 전달을 한다고 볼 수 있습니다.
스프링 시큐리티는 기본적으로 인증을 하지 않거나 세션을 생성하지 않는 정책을 설정 할 경우 세션을 생성하지 않습니다. 하지만 만약 WAS 가 세션을 생성하거나 다른 영역에서 세션을 생성할 경우 그 세션을 사용합니다.
참고하시기 바랍니다.
Q. 세션 생성
일반적으로 세션을 WAS 가 먼저 생성을 합니다.
스프링 시큐리티는 세션을 참조할 때 기본적으로는 request.getSession(false) 입니다.
즉 세션을 가지고 오는데 세션이 있으면 참조하고 없으면 null 을 받습니다.
이 때 톰캣이 세션을 먼저 생성했다면 그 세션을 인증 유무에 관계 없이 그냥 이용한다는 의미로 보시면 됩니다.
그런데 만약에 아무데서도 세션을 생성하거나 존재하지 않았다고 가정한다면 스프링 시큐리티는 인증을 성공한 경우 request.getSession(true) 로 전환되어 직접 세션을 생성한다고 보시면 됩니다.
참고
- Total
- Today
- Yesterday
- rocky
- 베리 심플
- elasticsearch
- docker
- window
- LocalDateTime
- jQuery
- Spring Security
- LocalDate
- 북리뷰
- maven
- k8s
- config-location
- Kotlin
- Spring
- mybatis config
- Github Status
- Mac
- input
- intellij
- oracle
- svn
- 오라클
- localtime
- Linux
- springboot
- Java
- Bash tab
- mybatis
- JavaScript
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |