JustDoEat
[vite,spring/문제해결]서버 인증 쿠키데이터를 읽어오지 못하는 현상. 본문
개발환경.
frontend: TypeScripts, React, Vite
Backend: Java, Spring Boot, Flask
Docker
해결과정 생략 및 결과만 보실 분들은 맨 아래만 참고 바랍니다.
개요.
API 테스트에서 로그인 후 인증정보를 받아오면, 서버에서 인증정보를 확인 후 인가된 사용자면 API호출이 가능하게 하는 방식이다.
Swagger를 이용하여 로그인API를 실행을 하면 인증정보가 생기게 되고, 그 후 다른 API호출을 하게 되면 문제없이 작동이 잘 되었다.
하지만 Docker 로 올린 frontend 컨테이너에서 backend(springBoot) 컨테이너로 API호출을 보낼 시 인증 관련 에러가 발생함.
페이지는 리다이렉트 되는데 서버로 부터 원하는 데이터가 넘어오지 않았다.
console.log로 response.data를 찍어봤을 때
위와 같이 HTML코드가 응답이 되는 현상을 식별을 하였다. 이 부분은 서버단에서 사용자가 로그인을 하지 않았을 시 로그인 페이지로 리다이렉트 해주는 정적 html 파일을 리턴해주는 현상이라고 한다.
(어쩐지 로그를 더 찍어보면 적어놓지도 않은 /login 400 error라는 에러가 나왔다.)
문제해결
일단 사용자가 로그인을 한다면
JSESSIONID라는
사실 소통의 부제가 있었다. 인증정보를 SESSION에 준다고 들어서, 개발자도구에 SESSION창에 들어가서 왜 SESSiON이 없지.. 하고 고민을 많이 했었다.
혹시나 해서 COOKIES에 들어갔는데 JSESSION이라는 쿠키를 발견하였고 질문을 하였다.. 혹시 세션이 아니라 쿠키에 저장되는 게 아닐까라는 의문이 들어서 다시 백엔드 팀원에게 물어보았다 확인 후... "네 맞습니다 말을 잘못했네요!"
오케이! 이제 문제가 무엇인지 알았다.
1. Swagger에서 인증 후 쿠키가 잘 넘어오는지 확인 후 Vite에서도 쿠키가 잘 넘어오는지 확인.
Swagger는 오케이 잘 넘어온다. Vite도 테스트 결과 어?
로그인을 해도 넘어오지 않는다.
왜 Cookies가 안 심어지는지 고민해 보자.
일단 서버단에서 해본 고민은
"포트번호가 달라서 CORS 설정문제 인가?"
"서버에서 쿠키를 심어주는 로직이 잘못된 건가?"
솔직히 서버단에서 문제가 있는 줄 알았다. 하지만 CORS설정 및 쿠키 전달 로직도 잘 되어있는 거 같고 3일째 그 자리에 멈추어 있었다.
그래서 프런트단에서 문제가 있는지 생각을 전환해 보았다.
프런트단에서 해본 고민은
"웹사이트 접속 시 "쿠키허용"이라는 문구를 봤었기 때문에, 쿠키를 받는 무언가를 허용을 해야 하나?"
=> 기대도 안 한 고민이었지만 이 부분이 문제의 원인이었다.
서버로부터 Cookies를 전달받는 방법.
credentials: 'include' // fetch 요청시 사용
혹은
withCredentials: true, // Axios요청 혹은 XMLHttpRequest 요청시 사용 가능
상황에 맞춰서 사용
동일포트 번호가 아닌 CROSS-Origin(다른 포트번호 간 통신)으로
fetch 요청을 할 때 위 부분을 필히 적어주어야 서버로부터 쿠키를 전달받을 수 있다.
credentials: 'include'란
는 웹 브라우저의 fetch API에서 사용하는 옵션으로, 요청을 보낼 때 쿠키와 인증 정보를 포함하도록 설정하고. 이 옵션은 크로스 오리진(Cross-Origin) 요청 시에도 쿠키를 포함하도록 할 수 있고, 혹은 요청 시 응답으로 쿠키를 받아 올 수 있다.
const response = await fetch(
'http://localhost:8080/api/v1/members/login',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
credentials: 'include',
},
);
Axios요청이 아닌 Fetch요청을 사용한 코드이므로 credentials: 'include'를 사용하였다.
단 한 줄의 코드만 추가했다고 모든 문제점이 해결이 되었다.
단 로그인 API 뿐만 아니라. 다른 API에도 해당 코드를 적어주어야 서버에서 쿠키를 전달받을 수 있다.
최종정리
크로스 오리진이 아닌 경우(즉, 동일 출처 요청인 경우)에는 withCredentials: true를 사용하지 않아도 쿠키가 자동으로 포함되고 받아진다. 하지만 Vite => spring서버로 요청을 보내는 경우이므로 동일출처 요청이 아니게 된다.
위와 같은 이유로 쿠키를 아무리 받고 보내려고 해도 기존의 방식으로는 할 수 없는 것이다.(보안 문제가 가장 크겠죠!)
이 경우 가장 먼저 CORS설정 확인을 해주어야 한다.
https://kingmusung.tistory.com/53
위 글은 spring boot CORS설정은 아니지만 CORS관련해서 문제해결 한 부분을 첨부해 보았다.
CORS설정이 완료되었다면, fetch 혹은 axios요청 시
credentials: 'include' // fetch 요청시 사용
혹은
withCredentials: true, // Axios요청 혹은 XMLHttpRequest 요청시 사용 가능
상황에 맞춰서 사용
위 코드를 추가해 주면 해결이 된다.