From ebba9eef0284319f7bf91ccde5350c031ee5dc30 Mon Sep 17 00:00:00 2001 From: JooHyunLee Date: Tue, 16 Apr 2024 11:16:25 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20#12=20RedisDao=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../account/auth/CustomUserDetails.java | 5 ++ .../common/GlobalExceptionHandler.java | 23 +++++---- .../account/component/JWTUtils.java | 21 +++++++- .../account/config/RedisConfig.java | 9 ++-- .../account/config/SecurityConfig.java | 12 ++++- .../account/controller/LoginController.java | 17 ++++--- .../account/controller/LogoutController.java | 5 +- .../account/controller/RefreshController.java | 13 ++++- .../account/dao/RedisDao.java | 35 -------------- .../account/entity/Account.java | 5 +- .../account/entity/BlackList.java | 5 +- .../account/entity/BookstoreAccount.java | 5 +- .../account/entity/Refresh.java | 5 +- .../exception/CookieNotExistException.java | 7 --- .../exception/JsonFieldNotMatchException.java | 5 +- .../TokenAlreadyExistsException.java | 5 +- .../exception/TokenHasExpiredException.java | 5 +- .../exception/TokenNotExistsException.java | 5 +- .../account/filter/CommonExceptionFilter.java | 5 +- .../account/filter/CustomLogoutFilter.java | 13 ++++- .../account/filter/LoginFilter.java | 28 +++++++++-- .../service/DefaultRefreshService.java | 15 ++++-- .../service/DefaultUserDetailsService.java | 15 ++++-- .../account/service/TokenService.java | 48 ++++++++++++++++--- 24 files changed, 212 insertions(+), 99 deletions(-) delete mode 100644 src/main/java/com/t3t/authenticationapi/account/dao/RedisDao.java delete mode 100644 src/main/java/com/t3t/authenticationapi/account/exception/CookieNotExistException.java diff --git a/src/main/java/com/t3t/authenticationapi/account/auth/CustomUserDetails.java b/src/main/java/com/t3t/authenticationapi/account/auth/CustomUserDetails.java index 2fba28e..7fd0da3 100644 --- a/src/main/java/com/t3t/authenticationapi/account/auth/CustomUserDetails.java +++ b/src/main/java/com/t3t/authenticationapi/account/auth/CustomUserDetails.java @@ -7,6 +7,11 @@ import java.util.ArrayList; import java.util.Collection; +/** + * UserDetails 를 구현하는 CustomUserDetails Class + * JWT 토큰에 들어가는 UserId, UserRole, Password를 반환하게 설정함 + * @author joohyun1996 (이주현) + */ public class CustomUserDetails implements UserDetails { private final UserEntity userEntity; diff --git a/src/main/java/com/t3t/authenticationapi/account/common/GlobalExceptionHandler.java b/src/main/java/com/t3t/authenticationapi/account/common/GlobalExceptionHandler.java index fe2c981..a876d98 100644 --- a/src/main/java/com/t3t/authenticationapi/account/common/GlobalExceptionHandler.java +++ b/src/main/java/com/t3t/authenticationapi/account/common/GlobalExceptionHandler.java @@ -1,6 +1,5 @@ package com.t3t.authenticationapi.account.common; -import com.t3t.authenticationapi.account.exception.CookieNotExistException; import com.t3t.authenticationapi.account.exception.TokenAlreadyExistsException; import com.t3t.authenticationapi.account.exception.TokenHasExpiredException; import com.t3t.authenticationapi.account.exception.TokenNotExistsException; @@ -12,23 +11,31 @@ @RestControllerAdvice public class GlobalExceptionHandler { + /** + * access, refresh 토큰이 없을 경우에 대한 예외 처리 핸들러 + * @return 403 Forbidden - 예외 메시지 반한 + * @author joohyun1996 (이주현) + */ @ExceptionHandler(TokenNotExistsException.class) public ResponseEntity> handleTokenNotExistsException(TokenNotExistsException tokenNotExistsException){ return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new BaseResponse().message(tokenNotExistsException.getMessage())); } - + /** + * access 토큰이 만료된 경우에 대한 예외 처리 핸들러 + * @return 403 Forbidden - 예외 메시지 반한 + * @author joohyun1996 (이주현) + */ @ExceptionHandler(TokenHasExpiredException.class) public ResponseEntity> handleTokenHasExpiredException(TokenHasExpiredException tokenHasExpiredException){ return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new BaseResponse().message(tokenHasExpiredException.getMessage())); } - + /** + * refresh, blacklist 토큰이 이미 Redis에 저장되어 있을 경우에 대한 예외 처리 핸들러 + * @return 400 Forbidden - 예외 메시지 반한 + * @author joohyun1996 (이주현) + */ @ExceptionHandler(TokenAlreadyExistsException.class) public ResponseEntity> handleTokenAlreadyExistsException(TokenAlreadyExistsException tokenAlreadyExistsException){ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new BaseResponse().message(tokenAlreadyExistsException.getMessage())); } - - @ExceptionHandler(CookieNotExistException.class) - public ResponseEntity> handleCookieNotExistsException(CookieNotExistException cookieNotExistException){ - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new BaseResponse().message(cookieNotExistException.getMessage())); - } } diff --git a/src/main/java/com/t3t/authenticationapi/account/component/JWTUtils.java b/src/main/java/com/t3t/authenticationapi/account/component/JWTUtils.java index 6423db8..01d393c 100644 --- a/src/main/java/com/t3t/authenticationapi/account/component/JWTUtils.java +++ b/src/main/java/com/t3t/authenticationapi/account/component/JWTUtils.java @@ -14,6 +14,10 @@ import java.time.ZoneId; import java.util.Date; +/** + * JWT 토큰 발급 및 claim을 사용하는 Util 클래스 + * @author joohyun1996 (이주현) + */ @Component public class JWTUtils { private Key key; @@ -33,11 +37,20 @@ public String getRole(String token){ public String getCategory(String token){ return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().get("category", String.class); } + /** + * access token과 refresh 토큰을 1대1로 맵핑해주는 임의의 UUID value + * @return String uuid + * @author joohyun1996 (이주현) + */ public String getUUID(String token){ return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().get("uuid", String.class); } - // 만료되었으면 true, 아니면 false + /** + * 토큰이 만료되었는지 확인하는 메소드 + * @return true if expired. else false + * @author joohyun1996 (이주현) + */ public Boolean isExpired(String token){ return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().getExpiration().before(new Date()); } @@ -54,7 +67,11 @@ public String createJwt(String category, String id, String role, String uuid, Lo .signWith(key, SignatureAlgorithm.HS256) .compact(); } - + /** + * access token 자동 재발급의 경우, 토큰의 잔여 시간이 5분 이하인지 check + * @return true / false + * @author joohyun1996 (이주현) + */ public Boolean checkReIssue(String token){ Date expiration = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().getExpiration(); LocalDateTime localDateTime = LocalDateTime.ofInstant(expiration.toInstant(), ZoneId.systemDefault()); diff --git a/src/main/java/com/t3t/authenticationapi/account/config/RedisConfig.java b/src/main/java/com/t3t/authenticationapi/account/config/RedisConfig.java index da40586..ebf03a1 100644 --- a/src/main/java/com/t3t/authenticationapi/account/config/RedisConfig.java +++ b/src/main/java/com/t3t/authenticationapi/account/config/RedisConfig.java @@ -10,7 +10,10 @@ import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; import org.springframework.data.redis.serializer.StringRedisSerializer; - +/** + * redis 연결을 위한 configuration 클래스 + * @author joohyun1996 (이주현) + */ @Configuration @EnableRedisRepositories public class RedisConfig { @@ -31,8 +34,8 @@ public class RedisConfig { * getConnection() 호출될 때 마다 새로운 LettuceConnection 생성 * Thread-safe 하다 * 동기, 비동기, 리액티브 api 모두 가능 - */ - + * @author joohyun1996 (이주현) + */ @Bean public RedisConnectionFactory redisConnectionFactory(){ RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(host, port); diff --git a/src/main/java/com/t3t/authenticationapi/account/config/SecurityConfig.java b/src/main/java/com/t3t/authenticationapi/account/config/SecurityConfig.java index f2c3fb5..56f7d25 100644 --- a/src/main/java/com/t3t/authenticationapi/account/config/SecurityConfig.java +++ b/src/main/java/com/t3t/authenticationapi/account/config/SecurityConfig.java @@ -17,7 +17,10 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutFilter; - +/** + * Spring Security 등록을 위한 configuration 클래스 + * @author joohyun1996 (이주현) + */ @Configuration @EnableWebSecurity @RequiredArgsConstructor @@ -35,7 +38,12 @@ public AuthenticationManager authenticationManager(AuthenticationConfiguration a public BCryptPasswordEncoder bCryptPasswordEncoder(){ return new BCryptPasswordEncoder(); } - + /** + * Security Filter Chain 설정. + * Auth-Server에서는 인증만 담당하기 때문에 다른 URL에 대해서는 설정 X + * @param HttpSecurity + * @author joohyun1996 (이주현) + */ @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http diff --git a/src/main/java/com/t3t/authenticationapi/account/controller/LoginController.java b/src/main/java/com/t3t/authenticationapi/account/controller/LoginController.java index 738a6f9..2044470 100644 --- a/src/main/java/com/t3t/authenticationapi/account/controller/LoginController.java +++ b/src/main/java/com/t3t/authenticationapi/account/controller/LoginController.java @@ -2,13 +2,15 @@ import com.t3t.authenticationapi.account.service.DefaultUserDetailsService; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.Map; - +/** + * Login 요청을 받는 RestController 클래스, 실제로는 UsernamePasswordAuthenticationFilter 때문에 동작하지 않는다. + * @author joohyun1996 (이주현) + */ @RestController public class LoginController { private final DefaultUserDetailsService service; @@ -16,15 +18,12 @@ public class LoginController { public LoginController(DefaultUserDetailsService service) { this.service = service; } - + /** + * LoginFilter 수행시 successfulAuthentication 메소드가 수행되고 해당 메소드에서 응답이 커밋됨 + * @author joohyun1996(이주현) + */ @PostMapping("/login") public String doLogin(HttpServletRequest request){ - // LoginFilter 수행시 successfulAuthentication 메소드가 수행되고 해당 메소드에서 응답이 커밋됨 return "login"; } - - @PostMapping("/logins") - public ResponseEntity> test(){ - return ResponseEntity.ok().body(Map.of("test","succeed")); - } } diff --git a/src/main/java/com/t3t/authenticationapi/account/controller/LogoutController.java b/src/main/java/com/t3t/authenticationapi/account/controller/LogoutController.java index 27c6d27..a8c18fc 100644 --- a/src/main/java/com/t3t/authenticationapi/account/controller/LogoutController.java +++ b/src/main/java/com/t3t/authenticationapi/account/controller/LogoutController.java @@ -2,7 +2,10 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; - +/** + * Logout 요청을 받는 RestController 클래스, 실제로는 LogoutFilter 때문에 동작하지 않는다. + * @author joohyun1996 (이주현) + */ @RestController public class LogoutController { @PostMapping("/logout") diff --git a/src/main/java/com/t3t/authenticationapi/account/controller/RefreshController.java b/src/main/java/com/t3t/authenticationapi/account/controller/RefreshController.java index 57b05fa..7de5148 100644 --- a/src/main/java/com/t3t/authenticationapi/account/controller/RefreshController.java +++ b/src/main/java/com/t3t/authenticationapi/account/controller/RefreshController.java @@ -8,12 +8,21 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - +/** + * access token의 재발급을 담당하는 rest controller + * @author joohyun1996 (이주현) + */ @RestController @RequiredArgsConstructor public class RefreshController { private final DefaultRefreshService defaultRefreshService; - + /** + * 토큰 재발급을 위한 api + * @param request,response + * @return 200 OK - access token 재발급 + * 403 Forbidden - access & refresh 만료시 + * @author joohyun1996 (이주현) + */ @PostMapping("/refresh") public ResponseEntity refresh(HttpServletRequest request, HttpServletResponse response) { return defaultRefreshService.refresh(request,response); diff --git a/src/main/java/com/t3t/authenticationapi/account/dao/RedisDao.java b/src/main/java/com/t3t/authenticationapi/account/dao/RedisDao.java deleted file mode 100644 index 043e798..0000000 --- a/src/main/java/com/t3t/authenticationapi/account/dao/RedisDao.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.t3t.authenticationapi.account.dao; - -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.stereotype.Component; - -import java.time.Duration; - -@Component -public class RedisDao { - private final RedisTemplate redisTemplate; - - public RedisDao(RedisTemplate redisTemplate) { - this.redisTemplate = redisTemplate; - } - - public void setValues(String key, String data) { - ValueOperations values = redisTemplate.opsForValue(); - values.set(key, data); - } - - public void setValues(String key, String data, Duration duration) { - ValueOperations values = redisTemplate.opsForValue(); - values.set(key, data, duration); - } - - public String getValues(String key) { - ValueOperations values = redisTemplate.opsForValue(); - return values.get(key); - } - - public void deleteValues(String key) { - redisTemplate.delete(key); - } -} diff --git a/src/main/java/com/t3t/authenticationapi/account/entity/Account.java b/src/main/java/com/t3t/authenticationapi/account/entity/Account.java index f4cdac0..43314cd 100644 --- a/src/main/java/com/t3t/authenticationapi/account/entity/Account.java +++ b/src/main/java/com/t3t/authenticationapi/account/entity/Account.java @@ -5,7 +5,10 @@ import lombok.experimental.SuperBuilder; import javax.persistence.*; - +/** + * 회원의 로그인 아이디를 담당하는 엔티티 + * @author joohyun1996 (이주현) + */ @Getter @Entity@Table(name = "accounts") @SuperBuilder diff --git a/src/main/java/com/t3t/authenticationapi/account/entity/BlackList.java b/src/main/java/com/t3t/authenticationapi/account/entity/BlackList.java index b28c61a..5673ee9 100644 --- a/src/main/java/com/t3t/authenticationapi/account/entity/BlackList.java +++ b/src/main/java/com/t3t/authenticationapi/account/entity/BlackList.java @@ -3,7 +3,10 @@ import lombok.*; import org.springframework.data.annotation.Id; import org.springframework.data.redis.core.RedisHash; - +/** + * logout 된 access token을 redis에 저장하는 엔티티 + * @author joohyun1996 (이주현) + */ @Builder @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/com/t3t/authenticationapi/account/entity/BookstoreAccount.java b/src/main/java/com/t3t/authenticationapi/account/entity/BookstoreAccount.java index 64683f2..75338e1 100644 --- a/src/main/java/com/t3t/authenticationapi/account/entity/BookstoreAccount.java +++ b/src/main/java/com/t3t/authenticationapi/account/entity/BookstoreAccount.java @@ -4,7 +4,10 @@ import lombok.experimental.SuperBuilder; import javax.persistence.*; - +/** + * 회원의 password를 저장하는 엔티티 + * @author joohyun1996 (이주현) + */ @Getter @Entity@Table(name = "bookstore_accounts") @SuperBuilder diff --git a/src/main/java/com/t3t/authenticationapi/account/entity/Refresh.java b/src/main/java/com/t3t/authenticationapi/account/entity/Refresh.java index 967ba5c..adb5831 100644 --- a/src/main/java/com/t3t/authenticationapi/account/entity/Refresh.java +++ b/src/main/java/com/t3t/authenticationapi/account/entity/Refresh.java @@ -5,7 +5,10 @@ import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.index.Indexed; - +/** + * refresh 토큰을 redis에 저장하는 엔티티 + * @author joohyun1996 (이주현) + */ @Getter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/com/t3t/authenticationapi/account/exception/CookieNotExistException.java b/src/main/java/com/t3t/authenticationapi/account/exception/CookieNotExistException.java deleted file mode 100644 index 4f14612..0000000 --- a/src/main/java/com/t3t/authenticationapi/account/exception/CookieNotExistException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.t3t.authenticationapi.account.exception; - -public class CookieNotExistException extends NullPointerException{ - public CookieNotExistException(String s) { - super(s); - } -} diff --git a/src/main/java/com/t3t/authenticationapi/account/exception/JsonFieldNotMatchException.java b/src/main/java/com/t3t/authenticationapi/account/exception/JsonFieldNotMatchException.java index 8006c3c..ce2f18a 100644 --- a/src/main/java/com/t3t/authenticationapi/account/exception/JsonFieldNotMatchException.java +++ b/src/main/java/com/t3t/authenticationapi/account/exception/JsonFieldNotMatchException.java @@ -1,7 +1,10 @@ package com.t3t.authenticationapi.account.exception; import java.io.IOException; - +/** + * 로그인시 회원의 id, pw에 해당하는 Json 객체가 올바르지 않은경우 발생하는 예외 + * @author joohyun1996 (이주현) + */ public class JsonFieldNotMatchException extends RuntimeException{ public JsonFieldNotMatchException(IOException e) { super(e); diff --git a/src/main/java/com/t3t/authenticationapi/account/exception/TokenAlreadyExistsException.java b/src/main/java/com/t3t/authenticationapi/account/exception/TokenAlreadyExistsException.java index b9bddf8..06408e1 100644 --- a/src/main/java/com/t3t/authenticationapi/account/exception/TokenAlreadyExistsException.java +++ b/src/main/java/com/t3t/authenticationapi/account/exception/TokenAlreadyExistsException.java @@ -1,5 +1,8 @@ package com.t3t.authenticationapi.account.exception; - +/** + * 새로운 토큰을 발급하는데, 이미 토큰이 존재하는 경우 발생하는 예외 + * @author joohyun1996 (이주현) + */ public class TokenAlreadyExistsException extends RuntimeException{ public TokenAlreadyExistsException(String e) { super(e); diff --git a/src/main/java/com/t3t/authenticationapi/account/exception/TokenHasExpiredException.java b/src/main/java/com/t3t/authenticationapi/account/exception/TokenHasExpiredException.java index c4bd8e4..0eaf97e 100644 --- a/src/main/java/com/t3t/authenticationapi/account/exception/TokenHasExpiredException.java +++ b/src/main/java/com/t3t/authenticationapi/account/exception/TokenHasExpiredException.java @@ -1,5 +1,8 @@ package com.t3t.authenticationapi.account.exception; - +/** + * 만료된 토큰으로 접근시 발생하는 예외 + * @author joohyun1996 (이주현) + */ public class TokenHasExpiredException extends RuntimeException{ public TokenHasExpiredException(String s) { super(s); diff --git a/src/main/java/com/t3t/authenticationapi/account/exception/TokenNotExistsException.java b/src/main/java/com/t3t/authenticationapi/account/exception/TokenNotExistsException.java index 46ad056..5e02c97 100644 --- a/src/main/java/com/t3t/authenticationapi/account/exception/TokenNotExistsException.java +++ b/src/main/java/com/t3t/authenticationapi/account/exception/TokenNotExistsException.java @@ -1,5 +1,8 @@ package com.t3t.authenticationapi.account.exception; - +/** + * auth - server로 접근하는 토큰에 대한 refresh토큰이 없는경우 발생하는 예외 + * @author joohyun1996 (이주현) + */ public class TokenNotExistsException extends RuntimeException{ public TokenNotExistsException(String s) { super(s); diff --git a/src/main/java/com/t3t/authenticationapi/account/filter/CommonExceptionFilter.java b/src/main/java/com/t3t/authenticationapi/account/filter/CommonExceptionFilter.java index 4b87a0f..67f954d 100644 --- a/src/main/java/com/t3t/authenticationapi/account/filter/CommonExceptionFilter.java +++ b/src/main/java/com/t3t/authenticationapi/account/filter/CommonExceptionFilter.java @@ -14,7 +14,10 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; - +/** + * Login, Logout Filter에서 발생하는 예외를 공통처리하는 Filter + * @author joohyun1996 (이주현) + */ public class CommonExceptionFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { diff --git a/src/main/java/com/t3t/authenticationapi/account/filter/CustomLogoutFilter.java b/src/main/java/com/t3t/authenticationapi/account/filter/CustomLogoutFilter.java index 0324a56..d77bcb8 100644 --- a/src/main/java/com/t3t/authenticationapi/account/filter/CustomLogoutFilter.java +++ b/src/main/java/com/t3t/authenticationapi/account/filter/CustomLogoutFilter.java @@ -13,7 +13,10 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Objects; - +/** + * CustomLogoutFilter 구현 + * @author joohyun1996 (이주현) + */ @RequiredArgsConstructor public class CustomLogoutFilter extends GenericFilterBean { private final JWTUtils jwtUtils; @@ -23,7 +26,13 @@ public class CustomLogoutFilter extends GenericFilterBean { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { doFilter((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse, filterChain); } - + /** + * 요청 url, method, header, token을 비교해서 로그아웃 처리 + * Logout 요청이 수락된 경우, 해당 요청에 사용된 access token은 redis에 저장해 blacklist로 등록한다 + * @return 204_No_Content + * @param request,response,filterChain + * @author joohyun1996 (이주현) + */ public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (!request.getRequestURI().matches("^\\/logout$")) { filterChain.doFilter(request, response); diff --git a/src/main/java/com/t3t/authenticationapi/account/filter/LoginFilter.java b/src/main/java/com/t3t/authenticationapi/account/filter/LoginFilter.java index 92a0a0b..cf26d1c 100644 --- a/src/main/java/com/t3t/authenticationapi/account/filter/LoginFilter.java +++ b/src/main/java/com/t3t/authenticationapi/account/filter/LoginFilter.java @@ -29,13 +29,21 @@ import java.util.Collection; import java.util.Iterator; import java.util.UUID; - +/** + * 로그인 과정을 담당하는 LoginFilter + * @author joohyun1996 (이주현) + */ @RequiredArgsConstructor public class LoginFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; private final JWTUtils jwtUtils; private final TokenService tokenService; - + /** + * 사용자가 입력한 login 정보를 가지고 인증 시도를 하는 메소드 + * @param request,response + * @return Authentication + * @author joohyun1996 (이주현) + */ @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { LoginDto loginDto = null; @@ -55,7 +63,14 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, password, null); return authenticationManager.authenticate(authToken); } - + /** + * 로그인 성공시 진행되는 메소드 + * 성공시 UserDetails에서 id, pw, authority 등을 꺼내 jwt 토큰 생성 + * access token은 response header에 담아 전달, refresh token은 redis에 저장 + * @return 200_OK, "Authorization : Bearer + accesstoken" + * @param request,response,chain,authentication + * @author joohyun1996 (이주현) + */ @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) { CustomUserDetails customUserDetails = (CustomUserDetails) authentication.getPrincipal(); @@ -77,7 +92,12 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR response.addHeader("Authorization", "Bearer " + access); response.setStatus(HttpServletResponse.SC_OK); } - + /** + * 로그인 실패시 수행되는 메소드 + * @return 401_Unauthorized, error message + * @param request,response,failed + * @author joohyun1996 (이주현) + */ @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { String errorMessage = null; diff --git a/src/main/java/com/t3t/authenticationapi/account/service/DefaultRefreshService.java b/src/main/java/com/t3t/authenticationapi/account/service/DefaultRefreshService.java index 4a8fa86..52c0fd0 100644 --- a/src/main/java/com/t3t/authenticationapi/account/service/DefaultRefreshService.java +++ b/src/main/java/com/t3t/authenticationapi/account/service/DefaultRefreshService.java @@ -11,13 +11,22 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Objects; - +/** + * refresh 요청을 담당하는 service + * @author joohyun1996 (이주현) + */ @Service @RequiredArgsConstructor public class DefaultRefreshService { private final JWTUtils jwtUtils; private final TokenService tokenService; - + /** + * 요청이 들어오면 header에 포함된 access token과 redis에 저장된 refresh token을 가지고 재발급 진행하는 메소드 + * @param request,response + * @return 200_OK, header "Authorization : Bearer + accesstoken" + * 401 UnAuthorized + * @author joohyun1996 (이주현) + */ public ResponseEntity refresh(HttpServletRequest request, HttpServletResponse response) { if (Objects.isNull(request.getHeader("Authorization"))) { throw new TokenNotExistsException("Access Token Not Exists"); @@ -54,8 +63,6 @@ public ResponseEntity refresh(HttpServletRequest request, HttpServletResponse response.addHeader("Authorization", "Bearer " + newAccess); return ResponseEntity.ok().build(); } - - // 그 외의 경우는 return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } diff --git a/src/main/java/com/t3t/authenticationapi/account/service/DefaultUserDetailsService.java b/src/main/java/com/t3t/authenticationapi/account/service/DefaultUserDetailsService.java index 4fe7cc0..1cf85b5 100644 --- a/src/main/java/com/t3t/authenticationapi/account/service/DefaultUserDetailsService.java +++ b/src/main/java/com/t3t/authenticationapi/account/service/DefaultUserDetailsService.java @@ -12,14 +12,22 @@ import org.springframework.stereotype.Service; import java.util.Objects; - +/** + * UserDetailsService 클래스를 구현하는 Custom Class + * @author joohyun1996 (이주현) + */ @Service @RequiredArgsConstructor public class DefaultUserDetailsService implements UserDetailsService { private final AccountRepository accountRepository; private final BCryptPasswordEncoder bCryptPasswordEncoder; - + /** + * 회원이 입력한 UserName, Password가 Database에 있는지 검증하는 메소드 + * @param username + * @return CustomUserDetails + * @author joohyun1996 (이주현) + */ @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserEntityDto userEntityDto = accountRepository.loadUserEntity(username); @@ -31,8 +39,7 @@ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundEx UserEntity userEntity = new UserEntity(); userEntity.setUsername(userEntityDto.getUsername()); userEntity.setUserId(userEntityDto.getUserId()); - userEntity.setPassword(userEntityDto.getPassword()); // 이게 맞는데 현재 회원에 password가 암호화 되어있지 않음 -// userEntity.setPassword(bCryptPasswordEncoder.encode(userEntityDto.getPassword())); + userEntity.setPassword(userEntityDto.getPassword()); userEntity.setRole(userEntityDto.getRole()); return new CustomUserDetails(userEntity); diff --git a/src/main/java/com/t3t/authenticationapi/account/service/TokenService.java b/src/main/java/com/t3t/authenticationapi/account/service/TokenService.java index eba0587..6d9d70f 100644 --- a/src/main/java/com/t3t/authenticationapi/account/service/TokenService.java +++ b/src/main/java/com/t3t/authenticationapi/account/service/TokenService.java @@ -10,26 +10,41 @@ import org.springframework.stereotype.Service; import java.util.Optional; - +/** + * Redis에 저장된 Refresh, BlackList 토큰의 CRUD를 담당하는 service 클래스 + * @author joohyun1996 (이주현) + */ @Service @RequiredArgsConstructor public class TokenService { private final RefreshRepository refreshRepository; private final BlackListRepository blackListRepository; - + /** + * Refresh Token을 Redis에 저장한다. + * @param refresh + * @author joohyun1996 (이주현) + */ public void saveRefreshToken(Refresh refresh){ if(refreshRepository.existsById(refresh.toString())){ throw new TokenAlreadyExistsException("Token Already Exists"); } refreshRepository.save(refresh); } + /** + * Logout 요청시 헤더에 있던 access token을 레디스에 저장한다 + * @param blackList + * @author joohyun1996 (이주현) + */ public void saveBlackListToken(String blackList){ if(blackListRepository.existsById(blackList)){ throw new TokenAlreadyExistsException("Token Already Exists"); } blackListRepository.save(BlackList.builder().blackList(blackList).build()); } - + /** + * refresh 토큰을 제거한다. + * @param refresh + */ public void removeRefreshToken(String refresh){ if(!refreshRepository.existsById(refresh)){ throw new TokenNotExistsException("Token Not Exists"); @@ -37,7 +52,11 @@ public void removeRefreshToken(String refresh){ Refresh newRefresh = refreshRepository.findById(refresh).get(); refreshRepository.delete(newRefresh); } - + /** + * Logout 요청시 access token과 UUID가 같은 refresh token을 찾아, 제거한다. + * @param uuid + * @author joohyun1996 (이주현) + */ public void removeRefreshTokenByUUID(String uuid){ Optional optionalRefresh = refreshRepository.findByUuid(uuid); if(!optionalRefresh.isPresent()){ @@ -45,18 +64,33 @@ public void removeRefreshTokenByUUID(String uuid){ } refreshRepository.delete(optionalRefresh.get()); } - + /** + * Refresh Token이 redis에 있는지 확인하는 메소드 + * @param refresh + * @return true/false + * @author joohyun1996 (이주현) + */ public boolean refreshTokenExists(String refresh){ return refreshRepository.existsById(refresh); } - + /** + * Access token과 매핑되는 refresh 토큰을 찾아 반환한다 + * @param uuid + * @return String refresh + * @author joohyun1996 (이주현) + */ public String findRefreshByUUID(String uuid){ if(refreshRepository.findByUuid(uuid).isEmpty()){ throw new TokenNotExistsException("Expired"); } return refreshRepository.findByUuid(uuid).get().getToken(); } - + /** + * access token과 일치하는 Refresh token이 있는지 찾는다 + * @param uuid + * @return true/fales + * @author joohyun1996 (이주현) + */ public Boolean refreshTokenExistsByUUID(String uuid){ return refreshRepository.existsByUuid(uuid); }