1. 세션 기반 인증

Untitled

세션 기반 인증 시스템에서 사용자가 로그인을 하면, 서버는 세션 저장소에 사용자의 정보를 조회하고 세션 ID를 발급한다. 발급된 ID는 주로 브라우저의 쿠키에 저장한다. 그 다음에 사용자가 다른 요청을 보낼 때마다 서버는 세션 저장소에서 세션을 조회한 후 로그인 여부를 결정하여 작업을 처리하고 응답을 한다.

단점 : 서버를 확장하기가 번거로워질 수 있다. 서버의 인스턴스가 여러 개가 된다면, 모든 서버끼리 같은 세션을 공유해야 하므로 세션 전용 데이터베이스를 만들어야 할 뿐 아니라 신경써야 될게 많다.

  1. 토큰 기반 인증

Untitled

토큰은 로그인 이후 서버가 만들어 주는 문자열이다. 해당 문자열 안에는 사용자의 로그인 정보가 들어 있고 해당 정보가 서버에서 발급되었음을 증명하는 서명이 들어 있다. 서버에서 만들어 준 토큰은 서명이 있기 때문에 무결성이 보장된다. 여기서 무결성이란 정보가 변경되거나 위조되지 않았음을 의미한다.

예를 들면 서버에서 정한 AccessToken 값이 있는데 그 시간이 만료가 되면 refreshToken을 api로 호출하면 서버가 로그아웃을 시키지 않고 바로 새로 생성된 AccessToken을 보내준다 그걸 cookie에 새로 담아주기만 하면 된다. 로컬스토리지에 담지 말기!!

const clientInstance = axios.create({
  // axios가 호출되면 Url 설정을 해줌
  baseURL: HOST
});

// Interceptors로 모든 호출이 될때 여기 먼저 가로챈다.
clientInstance.interceptors.request.use(
  async config => {
    let accessToken = await getAccessToken();

    config.headers['Authorization'] = accessToken;
    // alert(JSON.stringify(config.headers));
    store.dispatch({
      type: GLOBAL_LOADING
    });
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);
clientInstance.interceptors.response.use(
  response => {
    // if (response.data.errCode < 0) {
    //   alert('서버 처리중 오류가 발생하였습니다.');
    // }
    store.dispatch({
      type: GLOBAL_LOADED
    });
    return response.data;
  },
  error => {
//예를 들면 
if (error?.response?.status == 401) {
// refresh api 호출이 될 것이다.
}

return Promise.reject(error);
  }
);
const JWT_FLEFIX = 'palnet ';
// token 만료 시간인지 체크하는 함수
export const checkTokenExpired = (token?: string) => {
  const decodedToken = decode<LoginData>(token as string);

  if (parseInt(decodedToken.exp) < moment().unix()) {
    return true;
  }

  return false;
};

// interceptors로 함수가 실행된다.
export const getAccessToken = async () => {
  let token = cookieStorage.getCookie(COOKIE_ACCESS_TOKEN);

  if (!token || token == undefined || token == 'undefined') {
    return '';
  }

  if (checkTokenExpired(token)) {
    //freshtoken 으로 재발급 진행.
    const refreshToken = getRefreshToken();
    //const isRefresh = store.getState()?.authState?.isRefresh;

    if (refreshToken) {
      //   if (!store.getState()?.authState?.isRefresh) {
      const decodeToken = decode<LoginData>(token as string);
      const cstmrSno: number = decodeToken.cstmrSno;

      const { data, errorCode } = await refreshTokenAPI(cstmrSno, refreshToken);
      if (errorCode === '-101') {
        cookieStorage.setCookie(COOKIE_REFRESH_TOKEN, '');
      }
      //REFHRESTH 토큰 넣기
      cookieStorage.setCookie(COOKIE_ACCESS_TOKEN, data.accessToken);
      cookieStorage.setCookie(COOKIE_REFRESH_TOKEN, data.refreshToken);
      token = data.refreshToken;

      //   }
    }
  }

  return JWT_FLEFIX + token;
};

현재 위 코드의 예재는 원래는 response에 값이 왔을때 401 에러가 떨어졌을때 사용자가 요청했던 url을 저장 시켜두었다가 핸들링 하는게 보통인데 아예 request에서 프론트단에서 미리 서버에서 내려준 만료시간을 가지고 있고 그걸 decode로 되어있는걸 풀어서 비교한다음 지났으면 그때 호출과 동시에 새로 리프래쉬 시켜주는 방식이다. 그래서 굳이 response에서 코드를 처리를 안해도 된다는 장점이 있을 것이다. 그리고 애초에 만료가 되었을때만 서버를 호출하기 때문에 서버 비용 절감도 이득을 볼 수 있을 것이다.