[Node][TIL] BackOffice project - 음식 배달 서비스 구현 - 인증 미들웨어 구성 (2)

Trippy·2023년 12월 18일
0

Node.js

목록 보기
26/28
post-thumbnail

이전에 배운 기술들 중에서 미들웨어라는 개념을 배웠었고, 아주 요긴하게 잘 사용하고 있었다.
특히 그 중에서 인증 미들웨어인데, 로그인을 한 상태로 api호출을 해야 할 경우 항상 인증 미들웨어를 거치고 감에 따라서 해당 사용자가 인가된 사용자인지 확인 후, 잘못된 방식으로 접근 한 사용자라면 차단시켜 준다.

이 미들웨어는 단순 인가를 걸러주는 것 이상으로 편리함을 제공해 주는데 한 번 만들어 놓고 나면 개발자가 해당 사용자임을 알아야하는 정보들을 끌어다 써야 할 상황에서 미들웨어만 통과시켜주면 자동으로 미들웨어에서 발급 해주는 해당 사용자의 정보들과 함께 제공된다. 그렇기 때문에 현재 로그인 한 사용자의 정보를 이용해 여러가지 api 처리를 할 수 있어서 편리하다.

현재 우리가 구현하고자 하는 프로젝트에는 User의 종류가 2가지 이다. 하나는 일반 소비자 유저, 또 다른 하나는 서비스를 제공하는 유저이다. 따라서 단 하나의 인증 미들웨어만을 통과하면 현재 두 유형의 유저들을 구별해줄 수 있는 방법이 없어서 향후 서버 개발자가 두 유형의 사용자를 구별해줘야 할 때마다 매번 어떤 사용자인지 식별해야하는 상황이 생긴다.


그래서 준비했다.

이름하여 사장님 미들웨어 이다.

일반 auth 미들웨어는 accessToken 기반으로 사용자의 UserId로 식별하지만 내가 만들고자 하는 사장님 미들웨어는 사업장의 Id (이하 본문에서는 RestaurantId 라고 한다.) ID를 사용하여 해당 사용자가 사업장 등록을 했는지에 따라서 db 비교 후 사업장 테이블에 해당 user의 id값이 없다면 사업자 등록이 되어 있지 않다는 로직을 가지고 있다.


먼저 미들웨어는 auth_middleware ---> auth_owner_middleware ---> 해당라우터 로 통과한다.

import { prisma } from "../utils/prisma/index.js";

// 소유자 권한 미들웨어
const auth_owner_middleware = async (req, res, next) => {
  try {
    console.log("----미들웨어 시작------");

    // 로그인한 사용자의 ID를 가져옴
    const { userId } = res.locals.user;
    // URL 파라미터에서 레스토랑 ID를 추출
    const { restaurantId } = req.params;

    // 사용자의 ID로 레스토랑 소유 여부 확인
    const owner = await prisma.restaurants.findUnique({
      where: {
        UserId: userId,
      },
    });

    // 미들웨어 실행 시작 로그 출력
    console.log("----미들웨어 실행 중------");

    // 소유자가 아닌 경우 권한 없음 응답
    if (!owner) {
      return res.status(401).json({
        success: false,
        message: "권한이 없습니다 (사장 등록 X)",
      });
    }
     // 다른 레스토랑의 소유자인 경우 권한 없음 응답
    if (owner.restaurantId !== +restaurantId) {
      return res.status(401).json({
        success: false,
        message: "권한이 없습니다(사장 등록 O, 다른 사장 페이지)",
      });
    }

    // 레스토랑 소유자 정보를 로컬 변수에 저장
    res.locals.owner = owner;

    // 다음 미들웨어로 이동
    next();
  } catch (error) {
    // 에러가 발생한 경우 세션 쿠키를 클리어하고 권한 없음 응답
    res.clearCookie("authorization");
    return res.status(401).json({
      message: "비정상적인 요청입니다.",
    });
  }
};

// 다른 파일에서 사용할 수 있도록 미들웨어 내보내기
export { auth_owner_middleware };

auth_middleware를 통과하고 왔기 때문에 로컬 변수에 저장된 userId와 url 파라미터의 restaurantId를 가져와서 사업장 db에서 소유 여부를 확인하고 if문으로 원하는 조건을 달아주게 된다.

레스토랑의 소유자 정보를 res.locals.owner 에 저장하여 다른 미들웨어나 라우터에서 사용할 수 있게 한다.

그런 다음 모든 조건문을 통과하고 나면 다음 미들웨어로 이동한다.

하지만 에러가 발생한 경우 세션 쿠키를 클리어하고 (accessToken 초기화) 권한 없음 응답을 반환한다.

보완점

1. 권한 부여 및 로직 분리

  • 현재 미들웨어에서는 권한 확인 로직과 함께 다른 역할도 수행하고 있는데, 이로 인해 미들웨어가 너무 많은 책임을 지고 있을 수 있다.
  • 권한 확인 로직을 별도의 함수로 분리하여, 미들웨어가 더 간결하고 읽기 쉽도록 만들 수 있다.
// 새로운 파일 (auth.js)에 권한 확인 로직 분리
import { prisma } from "../utils/prisma/index.js";

const checkOwnerPermission = async (userId, restaurantId) => {
  const owner = await prisma.restaurants.findUnique({
    where: {
      UserId: userId,
    },
  });

  if (!owner) {
    return false; // 소유자가 아닌 경우
  }

  if (owner.restaurantId !== +restaurantId) {
    return false; // 다른 레스토랑의 소유자인 경우
  }

  return true; // 권한이 있는 경우
};

export { checkOwnerPermission };
// 새로운 파일 (auth.js)에 권한 확인 로직 분리
import { prisma } from "../utils/prisma/index.js";

const checkOwnerPermission = async (userId, restaurantId) => {
  const owner = await prisma.restaurants.findUnique({
    where: {
      UserId: userId,
    },
  });

  if (!owner) {
    return false; // 소유자가 아닌 경우
  }

  if (owner.restaurantId !== +restaurantId) {
    return false; // 다른 레스토랑의 소유자인 경우
  }

  return true; // 권한이 있는 경우
};

export { checkOwnerPermission };

상수 이용

  • 코드에서 사용하는 마법 숫자 및 문자열을 상수로 정의하여 코드를 읽기 쉽게 만들 수 있다.
// 상수 정의
const NO_OWNER_MESSAGE = "권한이 없습니다.";
const ABNORMAL_REQUEST_MESSAGE = "비정상적인 요청입니다.";

// 미들웨어에서 상수 사용
if (!hasPermission) {
 return res.status(401).json({
   success: false,
   message: NO_OWNER_MESSAGE,
 });
}

// ...

} catch (error) {
 res.clearCookie("authorization");
 return res.status(401).json({
   message: ABNORMAL_REQUEST_MESSAGE,
 });

세션 관리

  • 보다 안전한 세션 관리를 위해 express-session과 같은 세션 관리 미들웨어를 사용할 수 있다.
  • 세션 관리 미들웨어를 사용하면 세션의 유지 및 보안 관련 설정을 편리하게 구성할 수 있다.
  • 필요한 경우 세션을 데이터베이스에 저장하여 보안을 강화할 수 도 있다.
profile
감금 당하고 개발만 하고 싶어요

0개의 댓글