스프링 부트 - 자동 로그인 (RememberMe)

Spring

Posted by kwon on 2020-05-06

스프링 부트 - 자동 로그인 (RememberMe)

  • 로그인을 하면 자동으로 JSESSEIONID가 생성된다.
    • JSESSEIONID는 웹 브라우저와 서버와의 연결고리이다.
  • 기본 세션의 timeout 값은 30분이다.(톰캣)
세션이 만료되더라도 로그인을 유지하고 싶을 때 사용하는 방법
  • Remember-me는 쿠키를 사용한다. 인증을 하면, 쿠키에 암호화한 인증 정보를 담아둔다. 이 값은 세션이 만료되었거나 세션이 없는 경우 같이 보내온 Remembe-me 쿠키가 있으면 그 쿠키에 있는 인증정보를 인증을 시도한다.

  • 인증을 성공하면, 새로운 세션 id와 쿠키가 발급된다.

  • 해시 기반의 쿠키 - 사용자의 username, password를 암호화(해싱)하여 쿠키에 담아둔다.

    • 그러면 요청에 해당하는 세션을 찾지 못할 때, 함께 보내온 RememberMe 쿠키가 있다면 그 쿠기에 들어있는 인증 정보로 인증을 시도한다.
    • 그 username, password로 인증이 되면 새로운 세션ID와 쿠키가 발급이 되는 것이다.
    • 이 쿠키가 탈취당한다면 그 계정은 탈취당한 것과 같다.
    • http.rememberMe().key("asfasasdf") 와 같이 사용 가능
  • 조금 더 안전한 방법

    • 쿠키 안에 랜덤한 문자열(토큰)을 만들어 같이 저장하고 매번 인증할 때마다 바꾼다.
    • username, 토큰
    • 쿠키가 탈취당한 경우 새롭게 인증을 하면 탈취당한 쿠키는 더 이상 사용이 불가능 하다.
    • 하지만 해커가 탈취한 쿠키로 먼저 인증을 하면 해커의 쿠키만 유효하게 된다.
    • 이 방법은 스프링 부트에서 지원하지 않음.
  • 조금 더 개선한 방법

    • username, 토큰(랜덤, 매번 바뀜), 시리즈(랜덤, 고정)
    • 쿠키가 탈취 당한 경우, 희생자는 유효하지 않은 토큰유효한 시리즈와 Username 으로 접속하게 된다.
    • 이 경우, 쿠키가 탈취당해 누군가에 의해 사용되었다는 뜻이 되므로
    • 모든 토큰을 삭제하여 해커가 더 이상 탈취한 쿠키를 사용하지 못하도록 방지할 수 있다.
    • 이렇게 되면 form기반의 로그인 창으로만 로그인을 하여 인증이 가능하게 된다.
  • SecurityConfig.java 에서 다음과 같이 사용 가능

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @Configuration
    @EnableWebSecurity // 스프링 시큐리티 설정을 직접하겠다는 뜻
    @RequiredArgsConstructor
    public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final AccountService accountService;
    private final DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.rememberMe()
    .userDetailsService(accountService)
    .tokenRepository(tokenRepository());
    }

    @Bean
    public PersistentTokenRepository tokenRepository() {
    // JDBC 기반의 tokenRepository 구현체
    JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
    jdbcTokenRepository.setDataSource(dataSource); // dataSource 주입
    return jdbcTokenRepository;
    }
    }
  • JdbcTokenRepositoryImpl가 사용하는 테이블이 있어야 한다.

  • 해당 스키마가 생성될 수 있도록 매핑이 되는 엔티티가 필요하다.

  • PersistentLogins.java : 쿠키 값을 사용하기 위한 엔티티
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @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;

    }
  • login.html에 로그인 유지 체크박스를 추가해준다.
    1
    2
    3
    4
    <div class="form-group form-check">
    <input type="checkbox" class="form-check-input" id="rememberMe" name="remember-me" checked>
    <label class="form-check-label" for="rememberMe" aria-describedby="rememberMeHelp">로그인 유지</label>
    </div>

참조
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1/dashboard