소셜 로그인 시 SQL 에러 (DB에 기존 리프레시 토큰이 존재하는 상황에서 로그인을 시도하면 중복 에러가 발생)
소셜 로그인(Kakao, Google)에서 'SQLIntegrityConstraintViolationException' 오류 발생.
동일한 'user_id'가 새로운 'refreshToken'을 삽입하려고 시도하여 고유 제약 조건을 위반하는 'refresh_token' 테이블에 대한 중복 항목을 표현.
2024-11-09T16:28:11.042+09:00 WARN 26908 --- [ecogrow-backend][nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1062, SQLState: 23000
2024-11-09T16:28:11.042+09:00 ERROR 26908 --- [ecogrow-backend][nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Duplicate entry '3' for key 'refresh_token.UKf95ixxe7pa48ryn1awmh2evt7'
2024-11-09T16:28:11.062+09:00 ERROR 26908 --- [ecogrow-backend][nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.DataIntegrityViolationException: could not execute statement [Duplicate entry '3' for key 'refresh_token.UKf95ixxe7pa48ryn1awmh2evt7'][/* insert for com.sw.ecogrowbackend.domain.auth.entity.RefreshToken */insert into refresh_token (token_id,user_id,id) values (?,?,?)]; SQL [/ insert for com.sw.ecogrowbackend.domain.auth.entity.RefreshToken /insert into refresh_token (token_id,user_id,id) values (?,?,?)]; constraint [refresh_token.UKf95ixxe7pa48ryn1awmh2evt7]] with root cause
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '3' for key 'refresh_token.UKf95ixxe7pa48ryn1awmh2evt7'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:118) ~[mysql-connector-j-8.3.0.jar:8.3.0]
📄 기존 소셜 로그인의 토큰 업데이트 로직 부족:
카카오 소셜 로그인 메소드에서 동일한 user_id에 대한 기존 토큰을 확인하지 않고 새 refreshToken을 DB에 직접 저장.
'RefreshTokenService.saveRefreshToken'을 사용하여 토큰 업데이트를 처리하는 일반 사용자 로그인과 달리 소셜 로그인은 이 서비스를 사용하지 않아 이전에 로그인한 사용자에게 중복 항목이 발생.
통일성 없는 토큰 관리 논리:
package com.sw.ecogrowbackend.domain.auth.dto;
import lombok.Getter;
@Getter
public class TokenResponseDto {
private Long userId;
private String accessToken;
private String refreshToken;
public TokenResponseDto(Long userId, String accessToken, String refreshToken) {
this.userId = userId;
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
}
📄 소셜 로그인 로직 수정:
refreshToken 관리를 위해 RefreshTokenService.saveRefreshToken을 사용하도록 KakaoService의 kakaoLogin 메서드를 업데이트.
/**
* 토큰 저장
*
* @param userId 사용자 ID
* @param refreshToken 리프레시 토큰
*/
@Transactional
public void saveRefreshToken(Long userId, String refreshToken) {
User user = userRepository.findById(userId).orElseThrow(
() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")
);
RefreshToken token = refreshTokenRepository.findByUserId(userId)
.orElseGet(() -> new RefreshToken(refreshToken, user));
token.updateToken(refreshToken);
refreshTokenRepository.save(token);
}
📄 카카오 로그인에서 TokenResponseDto를 사용:
일반 로그인 프로세스와 일치하도록 accessToken 및 refreshToken을 모두 사용하여 TokenResponseDto를 반환하도록 카카오 로그인 방법을 수정.
📄 API 응답 통합:
통합된 TokenResponseDto를 반환하도록 kakaoLogin API 엔드포인트를 수정하여 일반 로그인과 소셜 로그인 모두에서 일관된 API 응답 형식을 제공.
➡️ 보안 위험 및 일반 로그인 논리와 통일성을 위해 기존 소셜 로그인에 쿠키 변환 로직 삭제
📄 소셜 로그인 프론트 코드 수정 (로컬 스토리지에 저장하고 클라이언트에 나타나게 수정)
📄 수정 전
Front
그러나 사용자별 쓰레기 기록을 조회하는 API, GET /api/waste/records/users/{userId}는 호출하지 못해 특정 유저의 쓰레기 기록을 기반으로 마이 페이지에 시각화를 실패하고 있음.
수정 전 Service와 Controller 로직은 단순히 Accesstoken만을 반환하고 클라이언트에 응답하는 구조로 설정이 되어 있기에 refreshToken과 user_Id가 포함되어 있는 TokenResponseDto로 통합하여 클라이언트에서 요청 시 서버에서 클라이언트로 필요한 정보를 모두 응답하도록 설정.
재로그인 시 RefreshToken 중복 문제
사용자별 데이터를 가져올 수 있도록 {userId}를 조회 문제를 해결할 수 있음.
📄 수정 후
Front
'const {accessToken, refreshToken, userId} = response.data;'