access Token 만료 후 todo/list 접속시도 에러 처리
안녕하세요.
access Token 정보 만료 후에 서버에서 보내는 메시지가 401 메시지로 옵니다.
그래서인지 jwtUtil.js 파일에서 처리를 못하는 문제가 있는 것이 맞을까요?
responseFail 을 아래와 같이 수정하는게 맞는지 무엇을 놓치고 있는 것인지 모르겠습니다.
http://localhost:3000/todo/list 를 10분 이상 경과후 실행했을 때 에러 메시지를 출력했었습니다.
import axios from "axios";
import {getCookie, setCookie} from "./cookieUtil";
import {API_SERVER_HOST} from "../api/hostApi";
const jwtAxios = axios.create()
const refreshJWT = async (accessToken, refreshToken) => {
const host = API_SERVER_HOST
const header = {headers: {"Authorization": `Bearer ${accessToken}`}}
const res = await axios.get(`${host}/api/member/refresh?refreshToken=${refreshToken}`, header)
console.log("----------------------")
console.log(res.data)
return res.data
}
//before request
const beforeReq = (config) => {
console.log("before request.............")
const memberInfo = getCookie("member")
if (!memberInfo) {
console.log("Member NOT FOUND")
return Promise.reject(
{
response:
{
data:
{error: "REQUIRE_LOGIN"}
}
}
)
}
const {accessToken} = memberInfo
// Authorization 헤더 처리
config.headers.Authorization = `Bearer ${accessToken}`
return config
}
//fail request
const requestFail = (err) => {
console.log("request error............")
return Promise.reject(err)
}
//before return response
const beforeRes = async (res) => {
console.log("before return response...........")
console.log(res)
//'ERROR_ACCESS_TOKEN'
const data = res.data
if (data && data.error === 'ERROR_ACCESS_TOKEN') {
const memberCookieValue = getCookie("member")
const result = await refreshJWT(memberCookieValue.accessToken, memberCookieValue.refreshToken)
console.log("refreshJWT RESULT", result)
memberCookieValue.accessToken = result.accessToken
memberCookieValue.refreshToken = result.refreshToken
setCookie("member", JSON.stringify(memberCookieValue), 1)
//원래의 호출
const originalRequest = res.config
originalRequest.headers.Authorization = `Bearer ${result.accessToken}`
return await axios(originalRequest)
}
return res
}
//fail response
const responseFail = async (err) => {
console.log("response fail error.............")
console.log(err)
const originalRequest = err.config;
// 토큰 만료로 인한 401 응답이라면 → refresh 시도
if (
err.response &&
err.response.status === 401 &&
!originalRequest._retry // 무한 루프 방지
) {
originalRequest._retry = true;
const memberCookieValue = getCookie("member");
try {
const result = await refreshJWT(
memberCookieValue.accessToken,
memberCookieValue.refreshToken
);
// 토큰 저장
memberCookieValue.accessToken = result.accessToken;
memberCookieValue.refreshToken = result.refreshToken;
setCookie("member", JSON.stringify(memberCookieValue), 1);
// 원래 요청 재시도
originalRequest.headers.Authorization = `Bearer ${result.accessToken}`;
return await axios(originalRequest);
} catch (refreshError) {
console.error("Refresh 실패, 로그아웃 처리 필요");
// 로그아웃 로직 연결 가능
localStorage.removeItem("token");
return Promise.reject(refreshError);
}
}
return Promise.reject(err);
}
jwtAxios.interceptors.request.use(beforeReq, requestFail)
jwtAxios.interceptors.response.use(beforeRes, responseFail)
export default jwtAxios
답변 3
0
JWTCheckFilter에서 401에러를 만들어서 보내시는 부분이 있네요
본인이 작성하신 코드
} catch (Exception e) {
log.error("JWT Check Failed: {}", e.getMessage());
// 4. 인증 실패 응답 세팅
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
String msg = new Gson().toJson(Map.of("error", "ERROR_ACCESS_TOKEN"));
try (PrintWriter writer = response.getWriter()) {
writer.println(msg);
}
// 5. 인증 정보 초기화 (중요)
SecurityContextHolder.clearContext();
}
--------------------------------
예제 코드
}catch(Exception e){
log.error("JWT Check Error..............");
log.error(e.getMessage());
Gson gson = new Gson();
String msg = gson.toJson(Map.of("error", "ERROR_ACCESS_TOKEN"));
response.setContentType("application/json");
PrintWriter printWriter = response.getWriter();
printWriter.println(msg);
printWriter.close();
}
0
음.. 좀 이상하네요..
서버의 JWTCheckFilter의 경우 accessToken을 검증한 후에 문제가 발생하면 catch로 빠지게 됩니다.
그런데 catch에서는 보내는 메세지는 그냥 200 번 상태 코드이고 'ERROR_ACCESS_TOKEN'으로 나가는게 맞습니다.
그러니 리액트 코드에서는 responseFail 에 걸리는게 아니라 beforeRes에 걸려야만 합니다.
제가 소스 코드를 실행해서 확인해 봐야 정확히 말씀드릴 수 있을 듯 합니다.
cookie_00@naver.com으로 소스 코드를 실행할 수 있는 링크나 방법등을 알려주시면 실행해서 원인을 좀 더 살펴보겠습니다.
0
안녕하세요, 인프런 AI 인턴입니다. Link님.
Access Token이 만료된 후 401 오류가 발생하며, 이로 인해 jwtUtil.js에서 적절히 처리되지 않는 상황을 겪고 계시는군요. jwtAxios 인터셉터 설정에 대해 함께 살펴보고 개선할 수 있는 부분을 안내해 드리겠습니다.
Access Token 처리 및 Refresh Token 갱신 흐름
기존 코드에서는 401 상태 코드가 반환될 때, 새로운 Access Token을 획득하기 위해 Refresh Token을 사용하여 토큰 갱신을 시도합니다. 이를 위해 responseFail과 beforeRes에 관련 로직이 포함되어 있습니다.
개선점 제안
Refresh Token 호출 검사:
refreshJWT함수에서 사용되는 URL 및 헤더 설정 등이 올바른지 한번 더 확인해 보세요. 특히 헤더의 Authorization 설정이 정확한지 여부가 중요합니다.무한 루프 방지:
originalRequest._retry플래그를 사용하여 무한 루프를 예방하고 있으므로, 이 부분이 잘 작동하고 있는지 확인하세요.로그아웃 로직 강화: Refresh Token이 손상되거나 실패할 경우 사용자를 로그아웃 시키는 로직을 준비해두는 것이 좋습니다. 이는 사용자 경험을 안정적으로 유지하는 데 도움을 줄 수 있습니다.
추가적인 사용자 안내: Refresh Token 갱신 과정이나 오류 발생 시 사용자에게 명확한 안내(알림 메시지 등)를 제공하여 혼란을 줄일 수 있습니다.
토큰 처리의 예외 상황
- 서버로부터 오는 오류 메시지가 정확히 “ERROR_ACCESS_TOKEN”인지, 401 상태 코드에 대해 적절히 대처하고 있는지 먼저 확인합니다.
- 토큰 만료 시 서버에서 응답 방식이 강의 예제와 동일한지, 커스터마이징이 필요한지 검토해보세요.
관련하여 참고할 수 있는 질문과 답변 URL을 추천해 드립니다. 이들 게시물에서는 토큰 만료 관련된 유사한 문제와 해결책을 논의하고 있습니다.
- jwt 10분 유효기간 끝나면 apiServer 쪽에서 Expired Exception 발생 질문: JWT 설정 및 연동 이슈에 대한 논의가 포함되어 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
동일하게 실습하는데 이상하게 페이지를 찾지 못하네요..
0
74
2
22. REST 방식 컨트롤러 만들기(2), 29. 등록처리 부분 질문이 있습니다.
0
74
2
37강. 강의수업듣다 질문드립니다.
0
57
2
TodoDTO test 함수
0
80
3
강사님 오타 있음요
0
77
2
No 1. 교제(ppt) soruce 복붙 문제 의 건
0
95
4
No 1. 교제(ppt) soruce 복붙 문제 의 건
0
70
3
17강 문의드립니다.
0
44
1
카카오 연동설정이 이제 안되는거 같아요
0
190
2
8장 마지막 강의 시 오류
0
98
4
혹시 뭐가 문제인지 알 수 있나요?
0
87
2
챕터: React-Router 설정
0
58
2
백)TODO관련
0
56
2
마리아 db 설치중 포트를 이미 사용중이라고 합니다
0
112
2
이강의 듣고 소화시켰다면 몇년차 정도 개발자라고 할수 있을까요?
0
105
1
CSR , SSR 의 수요 궁금증 질문
0
83
2
섹션5부터...
0
73
1
간단한 코드 질문!!
0
61
2
tbl_todo 질문입니다
0
65
2
수업 외 질문인데 'tbl'이 무슨 의미인가요???
0
291
2
엔티티클래스에서 질문입니다
0
78
2
수정시 writer값이 삭제되는 오류
0
42
2
교안 31 오타 수정해주세요
0
64
2
쿠키에 accessToken, refreshToken을 담고, 조회 시에 undefined
0
80
1





