From b2eb834c120be2139b05b1c9494fd26051bec851 Mon Sep 17 00:00:00 2001 From: Kwak Seong Joon Date: Fri, 24 Jan 2025 09:21:33 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20filter=EC=97=90=EC=84=9C=20jwt=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20-=20#154?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filter/OptionalAuthenticationFilter.java | 32 ++++++++----------- .../filter/RequiredAuthenticationFilter.java | 27 ++++++---------- .../src/main/java/com/cakey/Constants.java | 1 + 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/cakey-api/src/main/java/com/cakey/common/filter/OptionalAuthenticationFilter.java b/cakey-api/src/main/java/com/cakey/common/filter/OptionalAuthenticationFilter.java index aa4de8b..d1de19b 100644 --- a/cakey-api/src/main/java/com/cakey/common/filter/OptionalAuthenticationFilter.java +++ b/cakey-api/src/main/java/com/cakey/common/filter/OptionalAuthenticationFilter.java @@ -1,5 +1,6 @@ package com.cakey.common.filter; +import com.cakey.Constants; import com.cakey.jwt.auth.JwtProvider; import com.cakey.jwt.auth.UserAuthentication; import jakarta.servlet.FilterChain; @@ -12,6 +13,7 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; +import org.apache.tomcat.util.http.parser.Authorization; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -21,8 +23,6 @@ public class OptionalAuthenticationFilter extends OncePerRequestFilter { //로그인 상관 X private final JwtProvider jwtProvider; - private static final String ACCESS_TOKEN = "accessToken"; - // 필터를 건너뛸 API 경로 목록 private static final List EXCLUDED_PATHS = List.of( "/api/v1/store/likes/latest/*", @@ -43,7 +43,8 @@ public class OptionalAuthenticationFilter extends OncePerRequestFilter { //로 "/api/v1/store/*/select/coordinate", "/api/v1/store/*/size", "/api/v1/store/*/information", - "/api/v1/store/*/kakaoLink" + "/api/v1/store/*/kakaoLink", + "api/v1/user/login" ); @Override @@ -60,26 +61,19 @@ protected void doFilterInternal( @NonNull FilterChain filterChain ) throws ServletException, IOException { - final String accessToken = getAccessTokenFromCookie(request); + final String accessToken = request.getHeader(Constants.AUTHORIZATION); + if (accessToken != null) { - final Long userId = jwtProvider.getUserIdFromSubject(accessToken); - SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(userId, null, null)); + final long userId = jwtProvider.getUserIdFromSubject(accessToken); + SecurityContextHolder + .getContext() + .setAuthentication(new UserAuthentication(userId, null, null)); } else { - SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(null, null, null)); + SecurityContextHolder + .getContext() + .setAuthentication(new UserAuthentication(null, null, null)); } filterChain.doFilter(request, response); } - - public String getAccessTokenFromCookie(@NonNull HttpServletRequest request) { - final Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if (ACCESS_TOKEN.equals(cookie.getName())) { - return cookie.getValue(); - } - } - } - return null; - } } diff --git a/cakey-api/src/main/java/com/cakey/common/filter/RequiredAuthenticationFilter.java b/cakey-api/src/main/java/com/cakey/common/filter/RequiredAuthenticationFilter.java index 0db2cdc..1abf5d1 100644 --- a/cakey-api/src/main/java/com/cakey/common/filter/RequiredAuthenticationFilter.java +++ b/cakey-api/src/main/java/com/cakey/common/filter/RequiredAuthenticationFilter.java @@ -50,7 +50,8 @@ public class RequiredAuthenticationFilter extends OncePerRequestFilter { "/api/v1/store/*/select/coordinate", "/api/v1/store/*/size", "/api/v1/store/*/information", - "/api/v1/store/*/kakaoLink" + "/api/v1/store/*/kakaoLink", + "api/v1/user/login" ); @@ -68,9 +69,13 @@ protected void doFilterInternal( @NonNull FilterChain filterChain ) throws ServletException, IOException { try { - final String token = getAccessTokenFromCookie(request); - final Long userId = jwtProvider.getUserIdFromSubject(token); - SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(userId, null, null)); + final String accessToken = request.getHeader(Constants.AUTHORIZATION); + final long userId = jwtProvider.getUserIdFromSubject(accessToken); + + SecurityContextHolder + .getContext() + .setAuthentication(new UserAuthentication(userId, null, null)); + filterChain.doFilter(request, response); // 다음 필터로 요청 전달 } catch (Exception e) { // 예외 발생 시 JSON 응답 생성 @@ -80,7 +85,7 @@ protected void doFilterInternal( response.setCharacterEncoding(Constants.CHARACTER_TYPE); response.setStatus(errorCode.getHttpStatus().value()); // HTTP 상태 코드 401 설정 - log.error("--------------------쿠키 없음------------------------"); //todo: 추후 삭제(테스트용) + log.error("--------------------토큰 없음------------------------"); //todo: 추후 삭제(테스트용) // `ApiResponseUtil.failure`를 이용해 응답 작성 final PrintWriter writer = response.getWriter(); writer.write(objectMapper.writeValueAsString( @@ -90,16 +95,4 @@ protected void doFilterInternal( return; // 체인 호출 중단 } } - - private String getAccessTokenFromCookie(final HttpServletRequest request) throws Exception { - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for(Cookie cookie : cookies) { - if (cookie.getName().equals("accessToken")) { - return cookie.getValue(); - } - } - } - throw new UserBadRequestException(ErrorBaseCode.UNAUTHORIZED); - } } \ No newline at end of file diff --git a/cakey-common/src/main/java/com/cakey/Constants.java b/cakey-common/src/main/java/com/cakey/Constants.java index c6734c4..2582724 100644 --- a/cakey-common/src/main/java/com/cakey/Constants.java +++ b/cakey-common/src/main/java/com/cakey/Constants.java @@ -4,5 +4,6 @@ public abstract class Constants { public static final String CHARACTER_TYPE = "utf-8"; public static final String BEARER = "Bearer "; public static final String AUTHCODE = "authorization_code"; + public static final String AUTHORIZATION = "Authorization"; } From 95e0cf837393050f382a091eee5897222bf9f38c Mon Sep 17 00:00:00 2001 From: Kwak Seong Joon Date: Fri, 24 Jan 2025 09:33:27 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20jwt=20=EA=B5=AC=ED=98=84=20-=20#154?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/cakey/user/service/UserService.java | 44 ++++--------------- .../src/main/java/com/cakey/Constants.java | 1 + .../com/cakey/user/dto/LoginSuccessRes.java | 12 +++-- .../com/cakey/user/facade/UserCreator.java | 2 - 4 files changed, 19 insertions(+), 40 deletions(-) diff --git a/cakey-api/src/main/java/com/cakey/user/service/UserService.java b/cakey-api/src/main/java/com/cakey/user/service/UserService.java index 923884a..e2dfaab 100644 --- a/cakey-api/src/main/java/com/cakey/user/service/UserService.java +++ b/cakey-api/src/main/java/com/cakey/user/service/UserService.java @@ -1,6 +1,7 @@ package com.cakey.user.service; +import com.cakey.Constants; import com.cakey.client.SocialType; import com.cakey.client.dto.LoginReq; import com.cakey.client.kakao.api.KakaoSocialService; @@ -27,6 +28,7 @@ import org.springframework.cache.annotation.CacheEvict; import org.springframework.http.ResponseCookie; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @@ -37,12 +39,9 @@ public class UserService { private final UserFacade userFacade; private final KakaoSocialService kakaoSocialService; - private final static String ACCESS_TOKEN = "accessToken"; - private final static String REFRESH_TOKEN = "refreshToken"; private final JwtProvider jwtProvider; - private final UserRetriever userRetriever; - + @Transactional public LoginSuccessRes login( final String authorizationCode, final SocialType socialType, @@ -62,7 +61,6 @@ public LoginSuccessRes login( throw new UserBadRequestException(UserErrorCode.KAKAO_LOGIN_FAILED); } - //플랫폼 아이디 final long platformId = kakaoUserInfo.id(); @@ -78,12 +76,12 @@ public LoginSuccessRes login( final Token newToken = jwtProvider.issueToken(savedUserId); //쿠키설정 - setAccessCookie(newToken.getAccessToken(), response); setRefreshCookie(newToken.getRefreshToken(), response); return LoginSuccessRes.of( savedUserId, - kakaoUserInfo.kakaoAccount().profile().nickname()); + kakaoUserInfo.kakaoAccount().profile().nickname(), + newToken.getAccessToken()); } else { //전에 이미 우리 유저 //리프레시 토큰 캐시 삭제 @@ -92,12 +90,12 @@ public LoginSuccessRes login( final Token newToken = jwtProvider.issueToken(userId); //쿠키 설정 - setAccessCookie(newToken.getAccessToken(), response); setRefreshCookie(newToken.getRefreshToken(), response); return LoginSuccessRes.of( userId, - kakaoUserInfo.kakaoAccount().profile().nickname()); + kakaoUserInfo.kakaoAccount().profile().nickname(), + newToken.getAccessToken()); } } @@ -114,7 +112,6 @@ public void logout(final long userId, final HttpServletResponse response) { } catch (NotFoundBaseException e) { throw new UserNotFoundException(UserErrorCode.USER_NOT_FOUND); } - deleteAccessCookie(response); deleteRefreshCookie(response); deleteRefreshToken(userId); } @@ -122,21 +119,9 @@ public void logout(final long userId, final HttpServletResponse response) { @CacheEvict(value = "refresh") public void deleteRefreshToken(final long userId) { } - //accessToken 쿠키 삭제 - public void deleteAccessCookie(HttpServletResponse response) { - ResponseCookie accessCookie = ResponseCookie.from(ACCESS_TOKEN, "") - .maxAge(0) // 쿠키 즉시 삭제 - .path("/") - .secure(true) - .sameSite("None") - .httpOnly(true) - .build(); - response.addHeader("Set-Cookie", accessCookie.toString()); - } - //refreshToken 쿠키 삭제 public void deleteRefreshCookie(HttpServletResponse response) { - ResponseCookie refreshCookie = ResponseCookie.from(REFRESH_TOKEN, "") + ResponseCookie refreshCookie = ResponseCookie.from(Constants.REFRESH_TOKEN, "") .maxAge(0) // 쿠키 즉시 삭제 .path("/") .secure(true) @@ -146,19 +131,8 @@ public void deleteRefreshCookie(HttpServletResponse response) { response.addHeader("Set-Cookie", refreshCookie.toString()); } - public void setAccessCookie(final String accessToken, final HttpServletResponse response) { - ResponseCookie accessCookie = ResponseCookie.from(ACCESS_TOKEN, accessToken) - .maxAge(30 * 24 * 60 * 60 * 1000L) /// 1달 - .path("/") - .secure(true) - .sameSite("None") - .httpOnly(true) - .build(); - response.setHeader("Set-Cookie", accessCookie.toString()); - } - public void setRefreshCookie(final String refreshToken, final HttpServletResponse response) { - ResponseCookie refreshCookie = ResponseCookie.from(REFRESH_TOKEN, refreshToken) + ResponseCookie refreshCookie = ResponseCookie.from(Constants.REFRESH_TOKEN, refreshToken) .maxAge(30 * 24 * 60 * 60 * 1000L) /// 1달 .path("/") .secure(true) diff --git a/cakey-common/src/main/java/com/cakey/Constants.java b/cakey-common/src/main/java/com/cakey/Constants.java index 2582724..d1f6e73 100644 --- a/cakey-common/src/main/java/com/cakey/Constants.java +++ b/cakey-common/src/main/java/com/cakey/Constants.java @@ -5,5 +5,6 @@ public abstract class Constants { public static final String BEARER = "Bearer "; public static final String AUTHCODE = "authorization_code"; public static final String AUTHORIZATION = "Authorization"; + public static final String REFRESH_TOKEN = "refreshToken"; } diff --git a/cakey-domain/src/main/java/com/cakey/user/dto/LoginSuccessRes.java b/cakey-domain/src/main/java/com/cakey/user/dto/LoginSuccessRes.java index f9b5ec1..cb3f5dd 100644 --- a/cakey-domain/src/main/java/com/cakey/user/dto/LoginSuccessRes.java +++ b/cakey-domain/src/main/java/com/cakey/user/dto/LoginSuccessRes.java @@ -6,11 +6,17 @@ @Builder(access = AccessLevel.PRIVATE) public record LoginSuccessRes( long userId, - String userName + String userName, + String accessToken ) { public static LoginSuccessRes of( final long userId, - final String userName) { - return LoginSuccessRes.builder().userId(userId).userName(userName).build(); + final String userName, + final String accessToken) { + return LoginSuccessRes.builder() + .userId(userId) + .userName(userName) + .accessToken(accessToken) + .build(); } } \ No newline at end of file diff --git a/cakey-domain/src/main/java/com/cakey/user/facade/UserCreator.java b/cakey-domain/src/main/java/com/cakey/user/facade/UserCreator.java index 388b784..b0f66a7 100644 --- a/cakey-domain/src/main/java/com/cakey/user/facade/UserCreator.java +++ b/cakey-domain/src/main/java/com/cakey/user/facade/UserCreator.java @@ -12,11 +12,9 @@ public class UserCreator { private final UserRepository userRepository; - @Transactional public long createUser(final UserCreateDto userCreateDto) { final User user = User.createUser(userCreateDto.userName(), userCreateDto.userRole(), userCreateDto.socialType(), userCreateDto.socialId(), userCreateDto.socialEmail()); - System.out.println(); final User savedUser = userRepository.save(user); return savedUser.getId(); }