추가된 코드
- token
- tokenRepository
- tokenService
- CustomLogoutSuccessHandler
코드 동작
- 로그아웃 후에도 기간이 남은 토큰은 재사용될 가능성이 있다. (토큰은 따로 처리하지 않기때문)
- 따라서 로그아웃시 로그아웃 핸들러를 통해 토큰을 따로 저장해둔다.
- 토큰인증필터에서 해당 토큰이 로그아웃 처리된 토큰인지 DB에서 비교하는 코드를 통해 확인가능하다.
// CustomLogoutSuccessHandler
@Override public void onLogoutSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
log.debug("CustomLogoutSuccessHandler.onLogoutSuccess ::::");
String requestTokenHeader = request.getHeader("Authorization");
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
String jwtToken = requestTokenHeader.substring(7);
LocalTime jwtTokenExpTime = getExpTime(jwtToken);
Token data = tokenService.insertToken(jwtToken,jwtTokenExpTime);
}
super.onLogoutSuccess(request, response, authentication);
}
public LocalTime getExpTime(String jwtToken){
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
Date jwtTokenExp = jwtTokenUtil.getExpirationDateFromToken(jwtToken); //jwtTokenUtil 에서 구한 Date
LocalDateTime time2 = LocalDateTime.ofInstant(jwtTokenExp.toInstant(), ZoneId.systemDefault()); //data -> LocalDataTime
LocalTime JwtTokenTime = LocalTime.of(time2.getHour(), time2.getMinute(), time2.getSecond()); //LocalDataTime -> LocalTime
log.debug("time :: " + JwtTokenTime);
return JwtTokenTime;
}
1. requestHeader 에서 토큰을 얻어서 만료시간을 구하는 getExpTime으로 보낸다.
2. getExpTime에서 jwtTokenUtil로 토큰을 보내 만료시간(jwtTokenExp) 을 구한다.
3. jwtTokenExp 객체는 Date이고, 우리가 사용할 데이터는 LocalTime이므로
java.util.Date -> java.time.LocalTime 으로 변경한다.
4. 토큰과 getExpTime에서 구한 LocalTime을 DB에 저장하기위해 tokenService로 보낸다.
// tokenService
public Token insertToken(String jwtToken, LocalTime jwtTokenExpTime){
log.debug("token service : " + jwtToken+" && " + jwtTokenExpTime);
Token tokenInsert = Token.builder()
.token(jwtToken)
.expirationTime(jwtTokenExpTime)
.build();
return tokenRepository.save(tokenInsert);
}
5. 받은 토큰과 만료시간을 DB에 저장한다.
DB에서는 받은 토큰과 만료시간을 이벤트 스케줄러를 통해 관리한다.
-- DB
CREATE EVENT IF NOT EXISTS my_delete_event
ON SCHEDULE EVERY '1' MINUTE STARTS '2022-01-01'
DO DELETE FROM token WHERE expirationTime < now();
6. 토큰의 만료기간이 현재시간을 지나면 토큰은 삭제된다.
JwtRequestFilter 에서 코드 동작
JwtRequestFilter 에서 해당토큰이 로그아웃 처리된 토큰인지 비교해야한다.
// jwtRequestFilter
...
if(tokenService.compareToken(jwtToken)){
// 로그아웃된 토큰이 아니면 정상적으로 동작
}else{
username = null;
jwtToken = null;
throw new ServletException("이미 로그아웃 처리된 token입니다");
}
// tokenService
...
public boolean compareToken(String jwtToken) {
int result = tokenRepository.compareToken(jwtToken);
log.debug("result : " + result);
return result == 0;
}
1. 필터의 jwtToken을 구하는 부분 다음에 로그아웃 토큰인지 검사하는 if문을 작성했다.
2. tokenService에서 해당 토큰이 있는지 없는지 확인 후 return
3. 다시 필터로 돌아와 해당 토큰이 로그아웃된 토큰이면 수행되는 코드를 작성한다
(임시로 필터에서 구한 username && jwtToken의 값을 제거하고 예외를 냈다.)
해야할 일
1. 로그아웃시 등록할 토큰이 정상적인 토큰인지?
2. 로그아웃 된 토큰이면 어떻게 에러를 내고 Vue에서 출력해야하나?
-> response.addHeader를 사용하여 에러 메시지를 담아주었다.
Vue에서 headers.header에 "ExpToken" 메시지가 들어오면 에러 메시지를 alert로 띄워주고 로그인 화면으로 돌아간다.
'Vue > Vue' 카테고리의 다른 글
Vue3) Vue-Router (0) | 2023.04.05 |
---|---|
Vue.js 3.0 시작하기 (0) | 2023.04.05 |
로그아웃 2 (Springboot + Vue) (0) | 2022.01.23 |
로그아웃 1 (Springboot + Vue) (0) | 2022.01.20 |
조회수 중복 방지-cookie (Springboot + Vue) (0) | 2022.01.18 |