스프링 부트 - 자동 로그인 (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
// 스프링 시큐리티 설정을 직접하겠다는 뜻
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AccountService accountService;
private final DataSource dataSource;
protected void configure(HttpSecurity http) throws Exception {
http.rememberMe()
.userDetailsService(accountService)
.tokenRepository(tokenRepository());
}
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"persistent_logins") (name =
public class PersistentLogins {
64) (length =
private String series;
false, length = 64) (nullable =
private String username;
false, length = 64) (nullable =
private String token;
"last_used", nullable = false, length = 64) (name =
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