Skip to content

Commit

Permalink
merge: 액세스토큰 쿠키에서 jwt 사용 - #154
Browse files Browse the repository at this point in the history
[FEAT] 액세스토큰 쿠키에서 jwt 사용 - #154
  • Loading branch information
sjk4618 authored Jan 24, 2025
2 parents 5711071 + 95e0cf8 commit 1bca069
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -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<String> EXCLUDED_PATHS = List.of(
"/api/v1/store/likes/latest/*",
Expand All @@ -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
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"

);

Expand All @@ -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 응답 생성
Expand All @@ -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(
Expand All @@ -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);
}
}
44 changes: 9 additions & 35 deletions cakey-api/src/main/java/com/cakey/user/service/UserService.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -62,7 +61,6 @@ public LoginSuccessRes login(
throw new UserBadRequestException(UserErrorCode.KAKAO_LOGIN_FAILED);
}


//플랫폼 아이디
final long platformId = kakaoUserInfo.id();

Expand All @@ -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 { //전에 이미 우리 유저

//리프레시 토큰 캐시 삭제
Expand All @@ -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());
}
}

Expand All @@ -114,29 +112,16 @@ 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);
}

@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)
Expand All @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions cakey-common/src/main/java/com/cakey/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ 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";
public static final String REFRESH_TOKEN = "refreshToken";

}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down

0 comments on commit 1bca069

Please sign in to comment.