Feat: 로그아웃 기능 추가 및 FCM 토큰 제거
This commit is contained in:
parent
0ac4c743ed
commit
33a70cf451
@ -12,7 +12,6 @@ import com.worlabel.global.config.swagger.SwaggerApiError;
|
||||
import com.worlabel.global.config.swagger.SwaggerApiSuccess;
|
||||
import com.worlabel.global.exception.CustomException;
|
||||
import com.worlabel.global.exception.ErrorCode;
|
||||
import com.worlabel.global.service.FcmService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
@ -51,8 +50,8 @@ public class AuthController {
|
||||
JwtToken newToken = authService.reissue(refresh);
|
||||
int id = jwtTokenService.parseId(newToken.getAccessToken());
|
||||
|
||||
response.addCookie(createCookie(newToken.getRefreshToken()));
|
||||
authService.saveRefreshToken(id, newToken.getRefreshToken(),refreshExpiry);
|
||||
response.addCookie(createRefreshCookie(newToken.getRefreshToken(), (int) (refreshExpiry / 1000)));
|
||||
authService.saveRefreshToken(id, newToken.getRefreshToken(), refreshExpiry);
|
||||
|
||||
return AccessTokenResponse.from(newToken.getAccessToken());
|
||||
} catch (CustomException e) {
|
||||
@ -62,11 +61,25 @@ public class AuthController {
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "로그아웃", description = "사용자의 JWT, FCM Token, 리프레시 토큰을 삭제합니다.")
|
||||
@SwaggerApiSuccess(description = "Logout")
|
||||
@SwaggerApiError({ErrorCode.INVALID_TOKEN, ErrorCode.INVALID_REFRESH_TOKEN, ErrorCode.USER_NOT_FOUND})
|
||||
@PostMapping("/logout")
|
||||
public void logout(@CurrentUser final Integer memberId, HttpServletRequest request, HttpServletResponse response) {
|
||||
// 쿠키에서 리프레시 토큰 삭제
|
||||
Cookie deleteCookie = createRefreshCookie(null, 0);
|
||||
response.addCookie(deleteCookie);
|
||||
|
||||
authService.deleteRefreshToken(memberId);
|
||||
authService.deleteFcmToken(memberId);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "로그인 중인 사용자 정보를 반환", description = "현재 로그인중인 사용자의 정보를 반환합니다.")
|
||||
@SwaggerApiSuccess(description = "Return Member Info")
|
||||
@SwaggerApiError({ErrorCode.INVALID_TOKEN, ErrorCode.INVALID_REFRESH_TOKEN, ErrorCode.USER_NOT_FOUND})
|
||||
@GetMapping("/profile")
|
||||
public MemberResponse getMemberInfo(@CurrentUser final Integer currentMember){
|
||||
public MemberResponse getMemberInfo(@CurrentUser final Integer currentMember) {
|
||||
return memberService.getMemberId(currentMember);
|
||||
}
|
||||
|
||||
@ -74,13 +87,13 @@ public class AuthController {
|
||||
@SwaggerApiSuccess(description = "Redis에 FCM 토큰이 저장됨")
|
||||
@SwaggerApiError({ErrorCode.INVALID_TOKEN, ErrorCode.INVALID_REFRESH_TOKEN, ErrorCode.USER_NOT_FOUND})
|
||||
@PostMapping("/fcm")
|
||||
public void saveFcmToken(@CurrentUser final Integer currentMember, @RequestBody final FcmTokenRequest tokenRequest){
|
||||
public void saveFcmToken(@CurrentUser final Integer currentMember, @RequestBody final FcmTokenRequest tokenRequest) {
|
||||
authService.saveFcmToken(currentMember, tokenRequest.getToken());
|
||||
}
|
||||
|
||||
private static String parseRefreshCookie(HttpServletRequest request) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if(cookies != null) {
|
||||
if (cookies != null) {
|
||||
return Arrays.stream(cookies)
|
||||
.filter(cookie -> "refreshToken".equals(cookie.getName()))
|
||||
.findFirst()
|
||||
@ -90,9 +103,9 @@ public class AuthController {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Cookie createCookie(String value) {
|
||||
private Cookie createRefreshCookie(String value, int time) {
|
||||
Cookie cookie = new Cookie("refreshToken", value);
|
||||
cookie.setMaxAge((int) (refreshExpiry / 1000));
|
||||
cookie.setMaxAge(time);
|
||||
cookie.setPath("/");
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setSecure(true); // 배포 시 HTTPS에서 사용
|
||||
|
@ -1,38 +0,0 @@
|
||||
package com.worlabel.domain.auth.handler;
|
||||
|
||||
import com.worlabel.domain.auth.service.AuthService;
|
||||
import com.worlabel.domain.auth.service.JwtTokenService;
|
||||
import com.worlabel.global.exception.CustomException;
|
||||
import com.worlabel.global.exception.ErrorCode;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CustomLogoutHandler implements LogoutHandler {
|
||||
|
||||
private AuthService authService;
|
||||
private JwtTokenService jwtTokenService;
|
||||
|
||||
@Override
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||
String token = request.getHeader("Authorization");
|
||||
try {
|
||||
String refreshedToken = token.substring(7);
|
||||
int memberId = jwtTokenService.parseId(refreshedToken);
|
||||
|
||||
authService.deleteRefreshToken(memberId);
|
||||
authService.deleteFcmToken(memberId);
|
||||
|
||||
log.debug("로그아웃된 사용자의 토큰이 삭제 됨 {}", memberId);
|
||||
} catch (Exception e) {
|
||||
throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,14 +14,14 @@ public class FcmRepository {
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public void save(int memberId, String token) {
|
||||
redisTemplate.opsForHash().put(CacheKey.fcmTokenKey(), memberId, token);
|
||||
redisTemplate.opsForHash().put(CacheKey.fcmTokenKey(), String.valueOf(memberId), token);
|
||||
}
|
||||
|
||||
public void delete(int memberId) {
|
||||
redisTemplate.opsForHash().delete(CacheKey.fcmTokenKey(), memberId);
|
||||
redisTemplate.opsForHash().delete(CacheKey.fcmTokenKey(), String.valueOf(memberId));
|
||||
}
|
||||
|
||||
public String getToken(int memberId) {
|
||||
return (String) redisTemplate.opsForHash().get(CacheKey.fcmTokenKey(), memberId);
|
||||
return (String) redisTemplate.opsForHash().get(CacheKey.fcmTokenKey(), String.valueOf(memberId));
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
package com.worlabel.global.config;
|
||||
|
||||
import com.worlabel.domain.auth.handler.*;
|
||||
import com.worlabel.domain.auth.service.CustomOAuth2UserService;
|
||||
import com.worlabel.global.filter.JwtAuthenticationFilter;
|
||||
import com.worlabel.domain.auth.handler.CustomAuthenticationDeniedHandler;
|
||||
import com.worlabel.domain.auth.handler.CustomAuthenticationEntryPoint;
|
||||
import com.worlabel.domain.auth.handler.OAuth2SuccessHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -24,6 +22,7 @@ import java.util.List;
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityConfig {
|
||||
|
||||
private final CustomAuthenticationDeniedHandler authenticationDeniedHandler;
|
||||
private final CustomAuthenticationEntryPoint authenticationEntryPoint;
|
||||
private final JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
@ -70,7 +69,6 @@ public class SecurityConfig {
|
||||
.requestMatchers("/swagger", "/swagger-ui.html", "/swagger-ui/**", "/api-docs", "/api-docs/**", "/v3/api-docs/**", "/ws/**").permitAll()
|
||||
.requestMatchers("/api/auth/reissue").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
// .anyRequest().permitAll()
|
||||
);
|
||||
|
||||
// OAuth2
|
||||
|
Loading…
Reference in New Issue
Block a user