[React] 로그인, 회원가입 구현 (2)

siwoo jang·2023년 12월 15일
0
post-thumbnail

로그인 시 로그인 유효성을 access token 하나당 30분으로 뒀는데,
기능 페이지에서 30분 이상 있을 시 토큰이 유효하지 않게 되어서 에러가 발생할 수 있다.

// index.js 중 일부 
  <BrowserRouter>
  <AuthProvider>
    <Routes>
      <Route path="/" element={<Index />} />
      <Route path="/login" element={<PublicRoute><LoginPage /></PublicRoute>}/>
      <Route path="/register" element={<PublicRoute><RegisterPage /></PublicRoute>} />
      <Route path="/profile" element={<ProtectedRoute><ProfilePage /></ProtectedRoute>} />
      <Route path="/mypage" element={<ProtectedRoute><CalendarPage /></ProtectedRoute>} />
      <Route path="/file-upload" element={<ProtectedRoute><FileUploaderPage /></ProtectedRoute>} />
      <Route path="/result" element={<ResultPage />} />
      <Route path="/magazine" element={<MagazinePage/>} />

      <Route path="/survey" element={<ProtectedRoute><SurveyPage/></ProtectedRoute>}/>
      <Route path="/product" element={<HaircareProductPage/>}/>

      <Route path="/about" element={<AboutPage></AboutPage>}/>

      <Route path="*" element={<Navigate to="/" replace />} />
    </Routes>
    </AuthProvider>
  </BrowserRouter>

이를 해결하기 위해 JWT 인증 방식을 추가해 쿠키를 사용하고,
ProtectedRoute로 감싼 페이지, 로그인 후에 접근할 수 있는 페이지들이 랜더링 되면
자동으로 access token과 refresh token이 갱신되게 기능을 추가했다.

import React, { useContext, useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import { AuthContext } from 'components/Functions/AuthContext';
import axios from 'axios';
import Cookies from 'js-cookie';

const ProtectedRoute = ({ children }) => {
  const { isLoggedIn } = useContext(AuthContext);

 
  // ProtectedRoute로 감싸진 페이지 접속시 sessionStorage와 cookie 에 있는 access , refresh token 을 갱신
  useEffect(() => {
      const refreshTokens = async () => {
          const refreshToken = Cookies.get('refresh-token');
          const accessToken = Cookies.get('access-token')
      
          let headers = {
            Authorization: `Bearer ${accessToken}`,
          };
      
          if (refreshToken) {

            try {
              const response = await axios.post(
                `백엔드 주소`,
                null,
                {
                  headers: headers,
                }
              );

              const { accessToken, refreshToken: newRefreshToken } = response.data;

              Cookies.set('refresh-token', newRefreshToken, { path: '/' });
              Cookies.set('access-token', accessToken, { path: '/' });

              sessionStorage.setItem('accessToken', accessToken);
              sessionStorage.setItem('refreshToken', newRefreshToken);

            } catch (error) {
              console.error('Token reissue failed:', error);
            }
          }
    };

        if (isLoggedIn) {
          refreshTokens();
          const intervalId = setInterval(refreshTokens, 60*60*25); // 25분 간격으로 토큰 갱신
          return () => clearInterval(intervalId); // 컴포넌트 언마운트 시 인터벌 정리
        }

  }, [isLoggedIn]);
  




  if (!isLoggedIn) {
    return <Navigate to="/login" />;
  }

  return children;
};

export default ProtectedRoute;

ProtectedRoute로 감싼 페이지에 들어가면 access token과 refresh token을 받아와서 쿠키 값을 갱신하고, 25분 간격으로 access token과 refresh token을 갱신해준다.

          const refreshToken = Cookies.get('refresh-token');
          const accessToken = Cookies.get('access-token')
      
          let headers = {
            Authorization: `Bearer ${accessToken}`,
          };
      
          if (refreshToken) {

            try {
              const response = await axios.post(
                `백엔드 주소`,
                null,
                {
                  headers: headers,
                }
              );

어려웠던 부분은 바로 이 부분이였다. 쿠키를 post 할 시에 header를 지정해줘야 하는데
자꾸 500 에러가 나서 꽤나 시간이 많이 들었다.
위와 같은 형식으로 헤더를 지정해서 같이 post 해주니 결과가 잘 출력 되었다.
axios로 쿠키를 post 할 시에 헤더구조를 저런식으로 설정해줘야 한다는 것을 잊지말자

profile
프론트/백엔드 개발자입니다

0개의 댓글