청소 플랫폼 만들기 (6)

김민준·2023년 8월 21일
0

청소 플랫폼 만들기 (5)+WIL

  1. 청소 플랫폼 만들기 (6)
  2. 클라우드 서비스 간단정리
  3. CORS(Cross Origin Resource Sharing)

참조한 페이지

1. 청소 플랫폼 만들기 (6)

계속해서 발생하는 문제
인증을 메서드마다 남발했는데 미들웨어로 통합하였다.
하지만 미들웨어가 자꾸 작동을 하지 않아서 시간을 많이 날려먹었다.

증상은 라우터에서 인증 미들웨어를 가져왔는데 미들웨어가 제대로 작동하지 않는 것이었다.
정확히는 계정마다 권한이 있고 권한의 등급에 따라서 접근할 수 있는 API를 차등하는 방식인데 그것이 작동하지 않았다.
해결책은 인증 미들웨어에서 권한을 확인하는 모듈을 내보내고, 라우터에서 적용하는 것이다.

//  인증 미들웨어
exports.hasMinimumPermission = (permission) => {
  return async (req, res, next) => {
    const userId = res.locals.userId;
    try {
      if (isNaN(userId) || userId < 1) {
        return res.status(400).json({ sucess: false, message: '허가된 유저만 사용가능합니다.' });
      }

      const userPermission = permissionCache.getPermissionCache(userId);

      if (!userPermission) {
        return res.status(400).json({ sucess: false, message: '허가된 유저만 사용가능합니다.' });
      }

      const grade = {
        admin: 3,
        owner: 2,
        guest: 1,
      };
      console.log('!!!!!!!!!!!!!!!!!!!!');
      if (grade[userPermission] >= grade[permission]) {
        return next();
      }

      return res.status(400).json({ message: '허가된 유저만 사용가능합니다.' });
    } catch (err) {
      console.error(err);
      res.status(400).json({ errorMessage: '잘못된 접근입니다.' });
    }
  };
};
//  라우터
const express = require('express');
const router = express.Router();

const CompanyController = require('../1controllers/company.controller');
const companyController = new CompanyController();

const { authorized, hasMinimumPermission } = require('../middlewares/auth-middleware');

// 회사 등록
router.post('/companies', authorized, hasMinimumPermission("owner"), companyController.createCompany);

// 회사 정보 조회
router.get('/companies', companyController.getCompanyInfo);

// 회사 정보 수정, 회사 및 관리자 전용
router.put('/companies/:companyId', companyController.updateCompanyInfo);

// 회사 정보 삭제, 회사 및 관리자 전용
router.delete('/companies/:companyId', companyController.deleteCompany);

module.exports = router;

2. 클라우드 서비스 간단정리

IaaS Infrastructure as a Service . 이아스
인터넷으로 하드웨어 인프라를 제공하는 서비스

PaaS Platform as a Service
인터넷으로 플랫폼을 제공하는 서비스

SaaS Software as a Service
사용자에게 완성된 앱을 제공하는 서비스

IaaS의 한 종류인 AWS EC2의 경우 물리서버를 제공하는 것이 아니라, 물리서버에서 가상화된 컴퓨터 환경인 인스턴스를 제공한다.

3. CORS(Cross Origin Resource Sharing)

브라우저에서 서로 다른 출처의 리소스를 받아오는 기술이다.
주의할 점은 서버가 아니라 브라우저에서 거른다는 점이다.
즉, CORS 정책을 위한하면 status는 200이 뜨는데 콘솔창에 오류가 뜨기 때문에 개념을 잘 모르면 어디가 문제인지 알기 어렵다.

출처란? : URL의 Protocol, Host, Port를 합친것이다.
브라우저 개발자 콘솔에 location.origin을 쳐서 확인할 수 있다.

유튜브에서 해보면 'https://www.youtube.com' 라는 출처가 나온다.
프로토콜 : https://
호스트 : www.youtube.com
포트 : 443
기본 포트는 생략되는데 프로토콜에 따라서 기본 포트가 달라진다고 한다.

HTTP: 80
HTTPS: 443
FTP: 21
SSH: 22
Telnet: 23
SMTP: 25
POP3: 110
IMAP: 143

즉, 'https://www.youtube.com' 가 유지되기만한다면, 중간이나 뒤에 다른 path나 query가 붙더라도 동일출처 정책이 유지된다고 볼 수 있다.

이러한 출처는 어떻게 정해지게 되는 걸까?
CORS에서는 세가지 종류의 요청이 있으며, 요청에 따라서 달라진다.

1. 예비 요청 Preflight Request : 기본적인 방식
OPTION 메서드를 이용하는 방법이다.
예시) 자바스크립트가 브라우저에게 "www.youtube.net"이라는 출처에서 리소스를 받아오라는 FETCH요청을 보내면,
브라우저는 header에 이것을 담아 Origin이라는 필드에 이것을 담아 서버에게 OPTION 예비 요청을 보낸다.
서버는 Access-Control-Allow-Origin이라는 필드에 "www.youtube.com"이라는 출처가 허용 되었다고 알려줄 것이다.

내가 요청한 "www.youtube.net" 과 "www.youtube.com" 은 다른 호스트를 가지므로 다른 출처이다.
즉, 서버에서는 정상적으로 응답을 했으므로 200을 반환하지만, 브라우저에서는 이것이 CORS 정책을 위반하였다고 판단하므로 콘솔에서는 빨간 콘솔 에러창이 뜨게 된다.
이 출처가 같은지 확인하는 방식은 브라우저마다 다르다고하며, 이미 퇴출된 IE의 경우 이러한 기능이 없다고 한다.

2. 단순 요청 Simple Request : 까다로운 방식
예비요청이 사라진 형태이다. 대신에 까다로운 조건들이 붙는다.

  • GET HEAD POST 요청만을 사용할 수 있다.
  • 헤더에 Accept Accept-Language Content-Language Content-Type Range 만을 사용할 수 있다.
  • 헤더에 Content-Type을 사용할시 application/x-www-form-urlencoded, multipart/form-data, text/plain 타입만 사용할 수 있다.

첫 조건은 만족하기 쉽지만, 둘째와 셋째조건은 까다롭다.

3. 인증된 요청 Credentialed Request : 보안에 관련된 방식
브라우저에서 요청을 보낼때는 쿠키/인증과 같은 보안과 관련된 값을 담아서 요청하지 않는다.
creditionals 요청을 사용하면 담을 수 있게 된다.
omit : 절대로 쿠키를 주고받지 않는다.
same-origin(기본값) : 출처와 같아야 자격증명 (쿠키, 기본 http 증명 등...)을 보낸다.
include : Origin을 호출했더라도, 항상 자격증명 (쿠키, 기본 http 증명 등...)을 보낸다.

include의 경우 Access-Control-Allow-Origin: * 와 같이 모든 출처를 허용한다는 의미다.
same-origin 이나 include를 사용하여 리소스 요청에 인증정보가 포함된다면 브라우저에서는 CORS 정책 위반 여부를 검사하기 위한 두가지 조건을 추가하게 된다고한다.

1. Access-Control-Allow-Origin에는 *를 사용할 수 없으며, 명시적인 URL이어야한다.
2. 응답 헤더에는 반드시 Access-Control-Allow-Credentials: true가 존재해야한다.

CORS 정책 위반을 피하기
1. Access-Control-Allow-Origin 에 적절한 값을 세팅한다.
정석적이고 가장 안전한 방법이다.

2. 리버스 프록싱
개발환경에서는 webpack-dev-server라는 라이브러리의 프록싱 기능을 이용해서 브라우저를 속일 수 있다고 한다.
브라우저가 보낸 요청의 출처가 Access-Control-Allow-Origin의 출처와 다를 경우, 브라우저에서 내보낸 요청을 Access-Control-Allow-Origin의 출처로 바꾸는 원리라고한다.
실제 환경에서는 앱 소스의 출처와 API 서버의 출처가 같은 경우에만 쓰여야한다고한다.

그 외에 img 태그에 출처를 넣어서 요청하면 CORS 정책 자체는 어기지않는다.
왜냐하면, 요청모드를 설정하는 Sec-Fetch-Mode 태그에 no-cors라는 값이 들어가게되고 CORS 정책 위반 여부를 검사하지 않기 때문이다.
심지어 브라우저는 이 헤더에 들어있는 응답을 자바스크립트에 알려주지 않아서 코드 레벨에서는 알 수 없다고 한다.

참조한 페이지

프로토콜 기본 포트 목록

Cross-Origin Resource Sharing (CORS)
Request: credentials property
CORS는 왜 이렇게 우리를 힘들게 하는걸까?
CORS(Cross-Origin-Resource Sharing) 란?

네이버 영어사전 : credential

profile
node 개발자

0개의 댓글

관련 채용 정보