[TIL] 24.09.12 THU

GDORI·2024년 9월 12일
0

TIL

목록 보기
39/79
post-thumbnail

CH3 개인과제 일부 수정 및 미들웨어 구현으로 필수/도전 과제는 완료되었다. 분리할 부분이 더 보였지만 제출 시간의 한계로... 거기까진 못하고 제출했다. 😰😰 구현한 미들웨어에 대해 짤막하게 적어보겠다.
그리고 마지막으로 서버 포트 관련하여 정리하고 글을 마치겠다.

구현한 미들웨어 목록

  • 토큰 인증 미들웨어
  • 에러핸들링 미들웨어
  • 에러로그 미들웨어 ( /utils/CustomErr 포함 )
  • 캐릭터 소유권 검증 미들웨어

토큰 인증 미들웨어

로그인 시 헤더에 반환된 토큰을 기준으로 JWT 인증이 필요한 라우트에서 request.header에 authorization이 있는지 확인 후
검증한다.

토큰이 없을 경우, Bearer 형식이 아닌경우, 페이로드에 담긴 유저 정보가 없는 토큰일 경우에는 에러를 발생시킨다.


export default async function (req, res, next) {
  try {
    const { authorization } = req.headers; // 헤더에서 토큰 정보 추출

    if (!authorization)
      // 토큰이 없을 시 에러
      throw new CustomErr("요청한 사용자의 토큰이 없습니다.", 404);

    const [tokenType, token] = authorization.split(" "); // 토큰 형식과 데이터 분리
    if (tokenType !== "Bearer")
      // 베어러 타입이 아닐경우 에러
      throw new CustomErr("토큰 타입이 Bearer 형식이 아닙니다.", 400);

    const decodedToken = jwt.verify(token, SECRET_CODE); // 토큰 디코딩
    const userId = decodedToken.userId; // 디코딩한 토큰의 페이로드 내 유저ID 삽입

    const user = await prisma.users.findFirst({
      where: { userId: userId },
    });
    // 해당하는 유저가 없을 시 에러
    if (!user) throw new CustomErr("토큰 사용자가 존재하지 않습니다.", 404);

    req.user = user; // request에 user 객체 설정
    next(); // 다음 미들웨어로 전달
  } catch (err) {
    return res.status(400).json({ message: err.message });
  }
}

캐릭터 소유권 검증 미들웨어

특정 라우터에서 중복된 부분이 있어 미들웨어로 만들어 추가해주었다.

인증 미들웨어를 거친 후 user 객체와 캐릭터 번호로 character 테이블에서 조회를 하고 있을 경우 character 객체로 다음 미들웨어로 전달해주고 아니면 에러를 반환.

export default async function (req, _, next) {
  try {
    // 인증 미들웨어에서 생성한 user와 URL 매개변수에서 추출
    const {
      user: { userNo },
      params: { characterNo },
    } = req;

    const character = await prisma.characters.findFirst({
      where: { characterNo: +characterNo }, // characterNo 와 일치한 데이터 요청
    });
    if (!character)
      throw new CustomErr("캐릭터가 정보가 존재하지 않습니다.", 404); // 캐릭터 객체가 없을 시 에러
    if (character.userNo !== userNo)
      throw new CustomErr("캐릭터 접근 권한이 없습니다.", 401); // 캐릭터 소유권자와 토큰 인증자가 다를 시 에러
    req.character = character; // request에 캐릭터 객체 설정
    next();
  } catch (err) {
    return res.status(400).json({ message: err.message });
  }
}

에러핸들링/ 에러 로그 미들웨어

커스텀 에러 클래스를 생성하여 에러를 throw할 때 에러 정보와
status code를 받아 처리하는 미들웨어를 만들었다.

try-catch 구문을 통해 에러 부분을 customErr로 throw 해주면, catch는 에러 미들웨어로 정보를 넘긴다.
에러 미들웨어에서는 해당 에러 내용을 처리한다.

에러로그 미들웨어는 에러가 생겼을 경우 로그를 터미널에 출력한다.

  • CustomErr Class
  constructor(message, statusCode) {
    super(message); // Error 클래스의 message 속성 설정
    this.statusCode = statusCode; // 추가적인 statusCode 속성 설정
  }
  • error 핸들링 미들웨어
export default function (err, req, res, next) {
  // statusCode 가 전달되지 않은 경우 지정 외 에러이므로 500 할당
  const statusCode = err.statusCode || 500;
  // 서버 에러 출력
  console.error(err);

  if (statusCode === 500)
    res.status(500).json({ errorMessage: "서버 내부 에러가 발생했습니다." });

  // 클라이언트에게 에러 메시지를 전달
  res.status(statusCode).json({
    errorMessage: err.message,
    statusCode: statusCode,
  });
}
  • error log 미들웨어

// winston 설정에서 로그 레벨을 error로 설정
const logger = winston.createLogger({
  level: "error", // error 로그만 출력
  format: winston.format.json(),
  transports: [
    new winston.transports.Console({
      level: "error",
    }),
  ],
});

export default function (req, res, next) {
  const start = new Date().getTime();

  res.on("finish", () => {
    // 응답속도 계산
    const duration = new Date().getTime() - start;

    if (res.statusCode >= 400) {
      // 오류 상태 코드일 경우 error 레벨로 로그
      logger.error(
        `Method: ${req.method}, URL: ${req.url}, Status: ${res.statusCode}, Duration: ${duration}ms`
      );
    }
  });
  next();
}

EC2 포트포워딩? ㅡ Apache2로 PROXY 서버 만들어 프록시패스 시켜주기

과제를 제출하기 위하여 EC2에 pm2로 서버를 올리고 도메인 연결 후 서버에 접속하는데 포트번호를 치는 것이 너무 귀찮아서
없애기로 했다.

방법은 일반적으로 포트포워딩이 있고 리눅스에서 iptables을 통해 변경할 수 있다고 한다.
허나, 웹 기술 상의 다양한 보안 공격에 대해 탄력적으로 대응하기 어렵다는 의견들이 있어서 프록시 서버를 구축하고
프록시 패스 ( 80으로 들어온 요청을 내가 원하는 포트로 보내줌 )를 설정하기로 했다.

sudo apt upgrade

아파치서버를 다운받기 위하여 apt를 최신버전으로 다운받는다.

sudo apt-get install apache2

위 명령어를 이용하여 관리자 권한으로 apache2 를 다운받아준다.

sudo vi /etc/apache2/sites-avaliable/000-default.conf

해당 경로에 있는 conf파일을 vi를 이용하여 열어준다.

<VirtualHost *:80>
        ServerName example.com
        ServerAdmin admin@email.com
        DocumentRoot /var/www/html
        ProxyRequests Off
        ProxyPreserveHost On
        ErrorLog ${APACHE_LOG_DIR}/error.log
        ProxyPass / http://localhost:원하는 포트/
        ProxyPassReverse / http://localhost:원하는 포트/
        <Proxy *>
        	Order deny,allow
        	Allow from all
        </Proxy>
</VirtualHost>

안에 있는 내용을 모두 지우고 위의 내용으로 복붙한다.

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_html
sudo service apache2 restart

마지막으로 아파치 활성화 명령어 및 재부팅 명령어를 입력하고 접속시도하면 된다!
출처
[Web] 9편 - Ubuntu 20.04에서 Apache2를 사용하여 3000포트를 포트 바꿔서 배포하기
AWS 의 EC2 로 우분투 서버 구축하였습니다. 포트 포워딩에 대해서.

주의

단, 리눅스 내 방화벽 설정따윈 하지 않은 나같은 코린이들의 경우인거고 리눅스 내에 방화벽 설정을 켜놓았다면
해당 포트에 대하여 허용해주어야 한다.

또 EC2 인스턴스를 사용중이라면, 인바운드 규칙에 지정한 포트를 추가해주어야 된다는 점~😁

profile
하루 최소 1시간이라도 공부하자..

0개의 댓글