Error - cookie 역직렬화 문제
| topics | 300-백엔드개발 307 인증 & 보안 |
| types | 에러해결 |
| tags | #cookie #serialization #spring-security |
Cookie 역직렬화 문제
쿠키에 객체 저장했다가 읽을 때 역직렬화 실패하는 경우.
상황
Spring Security에서 OAuth2 인증 후 쿠키에서 AuthorizationRequest 읽으려다 에러 발생.
java.io.InvalidClassException: ... local class incompatible:
stream classdesc serialVersionUID = xxx, local class serialVersionUID = yyy
or
SerializationException: Failed to deserialize object
왜 발생할까
1. 클래스 변경됨
배포하면서 클래스 구조가 바뀌면 기존 쿠키의 직렬화된 데이터와 호환 안 됨.
2. serialVersionUID 없음
public class MySession implements Serializable {
// serialVersionUID 없으면 클래스 바뀔 때마다 자동 생성됨
private String data;
}
3. 쿠키 인코딩 문제
Base64 인코딩/디코딩 과정에서 깨지는 경우.
해결 방법
1. serialVersionUID 명시
public class MySession implements Serializable {
private static final long serialVersionUID = 1L;
private String data;
}
왜 이렇게 했냐면: 명시적으로 버전 관리하면 클래스 변경해도 호환성 유지 가능.
2. 쿠키 대신 세션 또는 DB 사용
쿠키에 객체 저장하는 건 사실 안티패턴임.
// 쿠키엔 ID만
Cookie cookie = new Cookie("sessionId", UUID.randomUUID().toString());
// 실제 데이터는 Redis나 DB에
redisTemplate.opsForValue().set(sessionId, authRequest, Duration.ofMinutes(10));
3. JSON으로 저장
직렬화 대신 JSON 사용하면 버전 문제 줄어듦.
// 저장
String json = objectMapper.writeValueAsString(authRequest);
String encoded = Base64.getUrlEncoder().encodeToString(json.getBytes());
Cookie cookie = new Cookie("auth", encoded);
// 읽기
String decoded = new String(Base64.getUrlDecoder().decode(cookieValue));
AuthRequest request = objectMapper.readValue(decoded, AuthRequest.class);
4. Spring Security OAuth2 쿠키 문제
HttpCookieOAuth2AuthorizationRequestRepository 쓸 때 자주 발생.
@Bean
public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
// 기본 구현 대신 커스텀
return new CustomCookieAuthorizationRequestRepository();
}
삽질 포인트
배포 후에만 에러 터지고 로컬에선 재현 안 됨.
2시간 삽질한 끝에 알아낸 것: 이전 버전 앱에서 생성한 쿠키가 브라우저에 남아있어서 그럼.
해결:
- 쿠키 이름 버전 붙이기:
auth_v2 - 또는 쿠키 만료시간 짧게
결론
- 쿠키에 복잡한 객체 저장하지 마라
- 저장해야 하면 JSON 사용
serialVersionUID꼭 명시- 배포 시 기존 쿠키 무효화 고려