Spring Security Remeber Me(로그인 정보 기억하기)

김건우·2023년 1월 30일
0

Spring Security

목록 보기
4/4
post-thumbnail

로그인 시, jsessionid(tomcat 컨테이너에서 세션을 유지하기 위해 발급하는 키)가 생긴다. 이것을 통해 웹브라우저와 서버가 연결된다.이 id에 해당하는 서버 쪽에 세션이라는 메모리가 있다. 만약 이것에 해당하는 객체가 서버 쪽에 없거나, 클라이언트가 키값을 보내지 않으면 세션을 찾지 못한다. 즉 세션에 넣어논 정보는 무의미하다.
스프링부트의 기본 세션 타임은 30분이다. 만약 이 값이 많이 커지면 불필요한 메모리 낭비가 심하다.메모리 낭비를 막으면서 로그인을 유지하고 싶으면 Remember-me라는 것을 이용해야한다.

RememberMe 기능이란

Remember-me는 쿠키를 하나 더 사용하는 것이다. 인증을 했을 때, 쿠키에 암호화한 인증정보를 담아서 넣어놓는다. 이 값은 세션이 만료되었거나, 세션이 없을 때 사용한다. 즉, 해당 요청에 해당하는 세션을 찾지 못할 때, 같이 보내온 Remember-me 쿠키가 있으면 그 쿠키에 들어있는 인증정보로 인증을 시도한다. 인증이 성공하면, 새로운 세션 id와 쿠키가 발급이된다.

안전성을 선택한 방법

랜덤한 토큰값(매번 바뀜)을 사용하고, 랜덤한 시리즈(고정)라는 것을 사용한다. 토큰은 매번 인증할 때마다 새로 바뀌고, 시리즈는 인증을 해도 바뀌지 않는다.이 경우 해커가 쿠키를 탈취하면, 사용자가 인증하려고 할 때, 유효하지 않은 토큰과 유효한 시리즈의 username으로 접속한다. 이 경우 토큰이 유효하지 않기 때문에 모든 토큰을 삭제하여 해커가 더 이상 탈취한 쿠키를 사용하지 못하도록 방지해준다. 그 후, form 기반으로 다시 로그인한다.

Spring Security에 RememberMe 추가

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final AccountService accountService;
    private final DataSource dataSource;
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.authorizeRequests()
                .mvcMatchers("/", "/login", "/sign-up", "/check-email", "/check-email-token",
                        "/email-login", "/check-email-login", "login-link", "/profile/*").permitAll()
                .mvcMatchers(HttpMethod.GET, "/profile/*").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login").permitAll()
                .and()
                .logout().logoutSuccessUrl("/")
                .and()
                .rememberMe().userDetailsService(accountService).tokenRepository(tokenRepository())
                .and().build();
    }
    
    @Bean
    public PersistentTokenRepository tokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        return jdbcTokenRepository;
    }
    
 }

기존의 spring security chain에서

.rememberMe().userDetailsService(accountService).tokenRepository(tokenRepository())

위와 같이 추가해준다. userDetailService를 구현한 메서드와 tokenRepository()를 사용하면 username, 토큰, 시리즈를 조합한 토큰이 생성된다.

DB 저장 방식

RemberMe기능은 토큰방식과 db방식이 있는데 여기서는 DB 방식으로 진행을 한다. DB방식의 경우 테이블을 생성하여 로그인시에 해당 테이블에 관련 정보를 저장하고 세션이 만료된경우 사용자의 Remember Me가 사용으로 설정(쿠키에 remember-me가 있는경우)이 되어 있는경우 테이블에 정보와 쿠키의정보를비교하여 자동으로 로그인을 시켜준다. 그렇게 때문에 테이블을 하나 생성을 하고 테이블에 데이타를 저장하는 서비스객체를 선언하고 UserDetailsService를 명시해줘야 한다.

PersistentLogins

@Table(name = "persistent_logins")
@Entity
@Getter @Setter
public class PersistentLogins {

    @Id
    @Column(length = 64)
    private String series;

    @Column(nullable = false, length = 64)
    private String username;

    @Column(nullable = false, length = 64)
    private String token;

    @Column(name = "last_used", nullable = false, length = 64)
    private LocalDateTime lastUsed;
}

그리고 잊지말아야 할 중요한 부분이있다. 프론트 단에서도 name="rember-me"를 지켜줘야 Spring security가 인식하고 로그인 정보를 기억 할 수 있다.

  <div class="form-group form-check">
      <input type="checkbox" id="rememberMe" name="remember-me"class="form-check-input"  checked>
      <label class="form-check-label" for="rememberMe" aria-describedby="rememberMeHelp">로그인 유지</label>
 </div>
  • Remember-me 토큰 생성🔽
profile
Live the moment for the moment.

0개의 댓글