본문 바로가기

Spring 정리ver2/Security

[baeldung] Control the Session with Spring Security

728x90

XML 은 안적음****

 

 

 

 

 

Spring Security가 HTTP 세션을 제어할 수 있는 방법

 

 

 

When Is the Session Created? 

We can control exactly when our session gets created and how Spring Security will interact with it:

  • always – A session will always be created if one doesn't already exist.
  • ifRequired – A session will be created only if required (default).
  • never – The framework will never create a session itself, but it will use one if it already exists.
  • stateless – No session will be created or used by Spring Security.

 Java configuration:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
    return http.build();
}

전체 애플리케이션이 아닌 Spring Security가 수행하는 작업에 대한 제어임<<<<<

Spring Security 는 필요 시점에 세션을 생성한다 = ifRequired

a more stateless application의 경우 "never" 옵션은 세션을 생성하지 않도록 한다

strictest session creation option, “stateless“ 일 경우에는 어떤 세션도 생성하지않도록 보장한다

Security filter chain — mainly the session-related parts such as HttpSessionSecurityContextRepository, SessionManagementFilter and RequestCacheFilter.

 

더 엄격한 제어 mechanisms 은 쿠기를 사용하지않는다는 의미로 모든 요청을 재인증해야한다

 

 

This stateless architecture 는 REST API, 또는 their Statelessness constraint 와 잘맞다

 Basic and Digest Authentication 같은 인증 mechanisms과도 작업이 가능하다

 

 

 

Under the Hood

인증 프로세스를 실행하기 전에 Spring Security는 요청 사이에 보안 컨텍스트를 저장하는 필터를 실행한다. -> SecurityContextPersistenceFilter

 

 

컨텍스트는 기본적으로 HTTP 세션을 저장소로 사용하는 HttpSessionSecurityContextRepository 전략에 따라 저장된다 .

엄격한 create-session=”stateless” 속성 의 경우 이 전략은 다른 NullSecurityContextRepository 로 대체되며 세션이 생성되거나 컨텍스트를 유지하는 데 사용되지 않는다.

 

 

 

Concurrent Session Control

이미 인증된 사용자가 재인증을 시도하면 몇 가지 방법으로 이벤트를 처리할 수 있다.

사용자의 활성된 세션을 무효화하고 새 세션으로 재인증하거나

두 세션을 동시에 존재하도록 할 수도 있다

 

 

 

동시 세션 제어 지원 방법

 define it as a Bean:

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
}

 

세션이 파괴될 때 Spring Security Session registry에 알림을 보낼 때 필수적이다

Spring Security session registry is notified when the session is destroyed.

 

동일한 사용자에 대해 여러 동시 세션을 허용하려면 Java 구성을 통해 수행할 수 있다.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().maximumSessions(2)
}

 

 

 

Session Timeout

Handling the Session Timeout

세션이 시간 초과된 후 사용자가 만료된 세션 ID 로 요청을 보내면 네임스페이스를 통해 구성 가능한 URL로 리디렉션시킬 수 있다

http.sessionManagement()
  .expiredUrl("/sessionExpired.html")
  .invalidSessionUrl("/invalidSession.html");

 

 

Configure the Session Timeout With Spring Boot

속성을 사용하여 임베디드 서버의 세션 시간 초과 값을 쉽게 구성할 수 있다.

server.servlet.session.timeout=15m
//세션이 15분 동안 활동이 없으면 만료시킴

Tomcat을 사용하도록 프로젝트를 구성한 경우 최소 1분의 세션 시간 초과에 대한 분 정밀도만 지원한다

즉, 예를 들어 시간 초과 값을 170s 로 지정하면 2분의 시간 초과가 발생한다.

목적을 위해 유사한 속성( spring.session.timeout )을 지원 하더라도 그것이 지정되지 않으면 자동 구성이 우리가 처음 언급한 속성 값으로 대체된다

 

 

 


Prevent Using URL Parameters for Session Tracking

 

URL에 세션 정보를 노출하는 것은 보안에 대한 위험이 증가한다

Spring 3.0 부터는 URL에 jsessionid를 추가하는 URL 재작성 로직은 이제 <http> 네임스페이스 에서 disable-url-rewriting=”true”를 설정하여 비활성화할 수 있다

servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));

JSESSIONID 를 저장할 위치 (쿠키 또는 URL 매개변수)를 선택한다.

 

 

 


Session Fixation Protection With Spring Security

프레임워크는 사용자가 다시 인증을 시도할 때 기존 세션에 발생하는 상황을 구성하여 일반적인 세션 고정 공격에 대한 보호 기능을 제공한다

Java configuration:

http.sessionManagement()
  .sessionFixation().migrateSession()

기본적으로 Spring Security는 이 보호 기능을 활성화한다(" migrateSession "). 

인증 시 새 HTTP 세션이 생성되고 이전 세션은 무효화되며 이전 세션의 속성이 복사된다.

 

 다른 옵션을 사용할 수 있다.

  • " none "이 설정되면 원래 세션이 무효화되지 않는다.
  • " newSession "이 설정되면 복사되는 이전 세션의 속성 없이 클린 세션이 생성된다.

 


세션 쿠키를 보호하는 방법

 

 

httpOnly  보안 플래그를 사용하여 세션 쿠키를 보호 할 수 있다

 

 

  • httpOnly : true이면 브라우저 스크립트가 쿠키에 액세스할 수 없다.
  • secure : 참이면 쿠키가 HTTPS 연결을 통해서만 전송된다.

 

기본적으로 http 전용 은 true이고 보안 은 false이다.

public class MainWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        // ...
        sc.getSessionCookieConfig().setHttpOnly(true);        
        sc.getSessionCookieConfig().setSecure(true);        
    }
}

 

 

Spring Boot를 사용하는 경우 application.properties 에서 다음 플래그를 설정할 수 있다

server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true

 

 

 

Filter 를 사용하여 이를 수동으로 수행할 수 있다

public class SessionFilter implements Filter {
    @Override
    public void doFilter(
      ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        Cookie[] allCookies = req.getCookies();
        if (allCookies != null) {
            Cookie session = 
              Arrays.stream(allCookies).filter(x -> x.getName().equals("JSESSIONID"))
                    .findFirst().orElse(null);

            if (session != null) {
                session.setHttpOnly(true);
                session.setSecure(true);
                res.addCookie(session);
            }
        }
        chain.doFilter(req, res);
    }
}

 

 


 

Working With the Session

Session Scoped Beans

A bean can be defined with session scope simply by using the @Scope annotation on beans declared in the web context:

@Component
@Scope("session")
public class Foo { .. }
@Autowired
private Foo theFoo;

Spring은 새 빈을 HTTP 세션의 수명 주기에 바인딩한니다.

 

 

Injecting the Raw Session Into a Controller

The raw HTTP Session can also be injected directly into a Controller method:

원시 세션 직접 주입

@RequestMapping(..)
public void fooMethod(HttpSession session) {
    session.setAttribute(Constants.FOO, new Foo());
    //...
    Foo foo = (Foo) session.getAttribute(Constants.FOO);
}

Obtaining the Raw Session

The current HTTP Session can also be obtained programmatically via the raw Servlet API:

ServletRequestAttributes attr = (ServletRequestAttributes) 
    RequestContextHolder.currentRequestAttributes();
HttpSession session= attr.getRequest().getSession(true); // true == allow create
728x90