Spring Session and Spring Security v1.0.2.RELEASE

2020. 9. 1. 14:58 Spring Framework/Spring boot

이 가이드는 어떻게 스프링 세션을 스프링 시큐리티와 함께 사용하는지 설명할 것이다. 당신의 어플리케이션에 스프링 시큐리티를 이미 적용했다는 가정하에 진행된다.

완전한 가이드는 다음의 시큐리티 샘플 어플리케이션링크에서 확인할 수 있다.

의존성 업데이트 하기 Updating Dependencies

스프링 세션을 사용하기전, 의존성 업데이트를 해야한다. 메이븐을 쓴다면 다음의 의존성을 추가해주자:

pom.xml
<dependencies>
        <!-- ... -->
        <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
        <version>1.0.2.RELEASE</version>
        <type>pom</type>
        </dependency>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.1.6.RELEASE</version>
        </dependency>
</dependencies>

스프링 설정 Spring Configuration

필수 의존성을 추가하면 스프링 설정을 생성할 수 있다. 스프링 설정으로 Servlet 필터를 만들어 HttpSession 구현체를 스프링 세션의 엄호하에 사용되는 구현체로 바꿔줘야한다. 다음의 스프링 설정을 추가하자:

@Configuration
@EnableRedisHttpSession 1
public class Config {

        @Bean
        public JedisConnectionFactory connectionFactory() {
                return new JedisConnectionFactory(); 2
        }
}
1@EnableRedisHttpSession 어노테이션은 Filter를 구현한 springSessionRepositoryFilter라는 이름의 스프링 빈을 만들어준다. 이 필터는 HttpSession를 스프링 세션의 엄호하에 사용되는 구현체로 대체해준다. 이 인스턴스에서 스프링 세션은 레디스에 엄호하에 있다.
2

스프링 세션을 레디스 서버에 연결하는 RedisConnectionFactory를 만들었다.RedisConnectionFactory that connects Spring Session to the Redis Server. 기본포트인 6379로 연결하도록 설정한다. 스프링 데이터 레디스의 자세한 설정정보는 레퍼런스 문서를 참고하자.

서블릿 컨테이너 초기화 Servlet Container Initialization

우리는 스프링 설정으로 Filter를 구현한 springSessionRepositoryFilter라는 이름의 스프링 빈을 만들어 스프링 세션에 엄호하에 사용되는 커스텀 구현체로 HttpSession을 대체하는데 쓴다.

우리의 Filter를 동작하게 하기 위해, 스프링은 우리가 설정한 Config 클래스를 불러와야한다. 어플리케이션이 이미 스프링 설정을 SecurityInitializer 클래스를 통해 실행되고 있기때문에 간단히 다음의 Config 클래스를 추가해주면된다:

src/main/java/sample/SecurityInitializer.java
public class SecurityInitializer extends
                AbstractSecurityWebApplicationInitializer {

        public SecurityInitializer() {
                super(SecurityConfig.class, Config.class);
        }
}

마지막으로 서블릿 컨테이너 (톰캣같은)가 모든 요청에 우리의springSessionRepositoryFilter 를 사용하게 만들야한다. 스프링세션의 springSessionRepositoryFilter가 스프링 시큐리티의 springSecurityFilterChain이 불러지기전에 호출되어야한다는 것은 극도로 중요하다. 스프링 시큐리티에서 사용하는 HttpSession은 반드시 스프링 세션의 엄호하에 있어야 한다. 다행스럽게도 스프링 세션은 이것을 극도로 쉽게 만들어주는 AbstractHttpSessionApplicationInitializer 이라는 유틸리티 클래스를 제공해준다. 밑의 예제를 보자:

src/main/java/sample/Initializer.java
public class Initializer extends AbstractHttpSessionApplicationInitializer {

}

클래스 이름 (Initializer)은 무엇이되도 상관없다. 중요한 것은 우리가 AbstractHttpSessionApplicationInitializer를 확장했다는 것이다.

AbstractHttpSessionApplicationInitializer 를 확장함으로서, springSessionRepositoryFilter라는 이름의 스프링 빈이 스프링 시큐리티의 Security’sspringSecurityFilterChain이전에 모든 요청을 처리하도록 서블릿 컨테이너와 함께 등록될 것이다.

시큐리티 샘플 어플리케이션 security Sample Application

시큐리티 샘플 어플리케이션 실행하기 Running the security Sample Application

소스 코드를 받아서 다음의 명령어를 호출함으로서 샘플을 실행할 수 있다:

샘플을 동작하려면 먼저 localhost에 레디스 2.8 또는 그 이후버전을 인스톨하고 기본 포트(6379)로 실행하자. 설치 설정이 다르면 JedisConnectionFactory에 레디스 서버를 해주면 된다.

$ ./gradlew :samples:security:tomcatRun

이제 http://localhost:8080/를 통해 어플리케이션에 접근할 수 있다.

시큐리티 샘플 어플리케이션 둘러보기 Exploring the security Sample Application

어플리케이션을 사용해보자. 다음의 로그인 정보를 입력하자:

  • Username user

  • Password password

Login 버튼을 누르면, 방금 입력한 사용자로 로그인됬다로 알려주는 메세지를 볼수 있다. 이 사용자 정보는 톰캣의 HttpSession 구현체가 아닌 레디스에 저장되어있다.

어떻게 동작하는가? How does it work?

톰캣의 HttpSession대신, 우리는 실제 레디스에 값을 저장하고 있다. 스프링 세션은 레디스의 엄호하에 있는 구현체로 HttpSession을 대체한다. 스프링 시큐리티의SecurityContextPersistenceFilter SecurityContext HttpSession 에 저장할때, 이는 레디스안에 저장된다.

새로운 HttpSession이 만들어질때, 스프링 세션은 사용자의 브라우저에 사용자의 세션ID를 가지고 있는 SESSION이라는 쿠키를 만든다. 계속 진행해서 쿠키를 둘러보자. (크롬이나 파이어폭스에서 쿠키값을 확인해볼수 있다)

redis-cli를 쓰면 세션값을 언제든지 레디스에서 손쉽게 삭제할 수 있다.예를 들면 리눅스 기반의 시스템에서는 다음과 같이 타입하면된다:

$ redis-cli keys '*' | xargs redis-cli del
 redis-cli 설치는 레디스 문서를 참고하자.

또는, 명시적인 키explicit key값을 삭제해도 된다. 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e의 값을 가지는 세션 쿠키를 삭제하려면 다음을 터미널에 타입하자:

$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

이제 다시 http://localhost:8080/ 를 방문해보면 더이상 인증되어있지 않은 걸 확인할 수 있다.



출처: https://springboot.tistory.com/13?category=620229 [스프링부트는 사랑입니다]