Web Server 기초

Dongwoo Joo·2023년 4월 4일
0

codestates bootcamp

목록 보기
25/48

학습 내용

CORS, SOP

요약
SOP는 다른 출처의 리소스 공유를 억제한다.
CORS는 다른 출처의 리소스 접근 권한을 제공한다.

SOP

정의와 예시

Same-Origin Policy 동일 출처 정책이다.
=> '같은 출처의 리소스만 공유 가능하다' 라는 정책이다.

Origin(출처) = 프로토콜 + 호스트 + 포트
이 중 하나라도 다르면 동일한 출처가 아니다.
예시) https://www.dongwoo.com:443/blog
--프로토콜-호스트-----------포트-

주의 사항) http, https의 기본 포트는 생략이 가능하다.
예시) https://dongwoo.com:443 vs https://dongwoo.com
-> https 프로토콜의 기본 포트는 443이다. 따라서, 동일한 출처이다.

예시2) http://codestates.com:80 vs http://codestates.com
-> http 프로토콜의 기본 포트는 80이다. 따라서, 동일한 출처이다.

SOP가 필요한 이유

해킹 위험 감소, 보안상 이유로 사용
잠재적 위험성이 있는 문서를 분리함으로써, 공격받을 수 있는 경로를 줄여준다.
부가 설명: SOP는 다른 사이트와의 리소스 공유를 제한한다.
이러한 보안상 이점의 이유로 모든 브라우저에서 SOP를 사용한다.

잠깐, 다른 출처의 리소스를 사용하는 경우는 많다.
요즘 어떤 사이트 건 카카오톡, 네이버, 구글, 애플 회원 정보로 로그인 하는 경우가 많다.
이것은 어떻게 설명할 것인가?

자, 이제 CORS를 알아보자.

CORS

Cross-Origin Resource Sharing(교차 출처 리소스 공유)
요역: 다른 출처의 리소스에 접근 권한을 부여하는 체제이다.
추가 HTTP 헤더를 사용해서, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.

CORS 설정을 통해 서버의 응답 헤더에 'Access-Control-Allow-Origin'을 작성하면 접근 권한을 얻을 수 있다. 즉, CORS 에러는 SOP 때문이다. 따라서, 설정을 해줘야 한다.

CORS 동작 방식

요약: CORS 동작 방식은 3가지가 있다.
Preflight / Simple / Credentialed Request
사전 요청 / 단순 요청 / 인증정보를 포함한 요청

Preflight Request

사전 요청이다.
실제 요청 전, OPTION 메서드로 사전 요청을 통해 해당 출처 리소스에 접근 권한이 있는지 확인한다.

왜 필요한가?
미리 권한을 확인할 수 있기 때문에, 리소스 측면에서 효율적이다.
CORS에 대비가 되어 있지 않은 서버를 보호할 수 있다.
실제 요청을 바로 보내면, 서버에서 "요청 처리"를 수행하고 응답을 보낸다.
응답이 에러가 나도, 이미 요청은 처리된 상태인 것이다. 실수로 보냈다면, 많은 정보를 잃을 수도 있다.

Simple Request

단순 요청이다.
특정 조건이 만족되면 Preflight 요청을 생략하고 요청을 보내는 것이다.

조건이 필요하다.
GET, HEAD, POST 요청 중 하나여야 한다.
자동으로 설정되는 헤더 외에, Accept, Accept-Language, Content-Language, Content-Type 헤더의 값만 수동으로 설정할 수 있다.
Content-Type 헤더에는 application/x-www-form-urlencoded, multipart/form-data, text/plain 값만 허용된다.

Credentialed Request

요청 헤더에 인증 정보르 담아 보내는 요청이다.
출처가 다를 경우에 별도 설정을 하지 않으면 쿠키를 보낼 수 없다.
민감한 정보이기 때문이다.
이 경우에는 프론트, 서버 양측의 CORS 설정이 필요하다.

프론트 측에서는 요청 헤더에 withCredentials : true
서버 측에서는 응답 헤더에 Access-Control-Allow-Credentials : true
서버 측에서 Access-Control-Allow-Origin 을 설정할 때,
모든 출처를 허용한다는 뜻의 와일드카드(*)로 설정하면 에러가 발생한다.
인증 정보는 출처를 정확하게 설정해야 한다.

*쿠키: 쿠키는 사용자가 방문한 웹사이트에서 사용자의 브라우저에 전송하는 작은 텍스트 조각입니다. 쿠키가 있으면 웹사이트에서 사용자의 방문에 관한 정보를 기억하여 다음번에 사이트에 방문했을 때 번거로운 작업을 피하고 더 유용하게 사이트를 활용할 수 있습니다.(출처: Google)

CORS 설정 방법

Node.js 서버

Node.js로 간단한 HTTP 서버를 만들 때, 응답 헤더 설정

const http = require('http');

const server = http.createServer((request, response) => {
// 모든 도메인
  response.setHeader("Access-Control-Allow-Origin", "*");

// 특정 도메인
  response.setHeader("Access-Control-Allow-Origin", "https://codestates.com");

// 인증 정보를 포함한 요청을 받을 경우
  response.setHeader("Access-Control-Allow-Credentials", "true");
})

Express 서버

Express 프레임워크를 사용해서 서버를 만드는 경우
cors 미들웨어를 사용해서 간단하게 CORS 설정할 수 있다.

const cors = require("cors");
const app = express();

//모든 도메인
app.use(cors());

//특정 도메인
const options = {
  origin: "https://codestates.com", // 접근 권한을 부여하는 도메인
  credentials: true, // 응답 헤더에 Access-Control-Allow-Credentials 추가
  optionsSuccessStatus: 200, // 응답 상태 200으로 설정
};

app.use(cors(options));

//특정 요청
app.get("/example/:id", cors(), function (req, res, next) {
  res.json({ msg: "example" });
});

*Express는 프레임워크이다.

과제

개요

브라우저에는 서버에 요청을 보내기 위해 fetch 같은 HTTP 요청을 보내는 도구가 기본적으로 내장되어 있다.
서버는 클라이언트(브라우저)의 HTTP 요청에 맞게 응답을 보낼 수 있도록 코드를 작성해야 한다.
Node.js는 HTTP 요청을 보내거나, 응답을 받을 수 있는 도구들을 제공한다.
HTTP 요청 처리 및 응답을 보내는 프로그램웹 서버(Web Server)이다.

과제에서는 Node.js의 http 모듈을 이용해 웹 서버를 만든다.
Node.js에서 파일을 읽거나 쓰기 위해 fs 모듈을 사용하듯,
HTTP 요청과 응답을 다루기 위해 HTTP 모듈을 사용한다.

아래 사이트를 참고하면 좋다.
HTTP 트랜잭션 해부 사이트
https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction
HTTP 모듈 사이트
https://nodejs.org/dist/latest-v16.x/docs/api/http.html

시작

서버 실행

커맨드에서 server/basic-server.js 파일을 실행한다.

node server/basic-server.js

nodemon을 이용하면, 서버를 매번 실행시킬 필요가 없다.
사용 순서
npm install nodemon
(CLI에 입력)

 "start": "nodemon server/basic-server.js"
// package.json의 "script"에 위 코드를 추가한다.

(vscode)
npx nodemon server/basic-server.js
(CLI에 입력)

HTTP 트랜잭션 해부 학습

서버 생성
축약 문법
메서드, URL, 헤더
요청 body
오류에 대한 간단한 설명
응답 HTTP 상태 코드
응답 헤더 설정
명시적인 헤더 데이터 전송
응답 body

과제 코드

const http = require('http');
const PORT = 4999;
const ip = 'localhost';

const server = http.createServer((request, response) => {
  if(request.method === "OPTIONS") {
    response.writeHead(200, defaultCorsHeader);
    response.end();
  }

  let body = [];
  request.on('data', (chunk) => {
    body.push(chunk);
  })
    .on('end', () => {
    body = Buffer.concat(body).toString()
  })
  {
    if(request.method === 'POST' && request.url === '/upper') {
      response.writeHead(201, defaultCorsHeader)
      response.end(body.toUpperCase()); }
      
      else if (request.method === 'POST' && request.url === '/lower') {
        response.writeHead(201, defaultCorsHeader)
        response.end(body.toLowerCase()); }
        
        else {
          response.writeHead(404, defaultCorsHeader)
          response.end();
        }
      }
    });

server.listen(PORT, ip, () => {
  console.log(`http server listen on ${ip}:${PORT}`);
});

const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
};

아는 것

CORS, SOP 개념

모르는 것

체득해야 할 것
1. HTTP 트랜잭션 코드 작성

  1. 에러 해결방안
    에러 1
    POST http://localhost:4999/upper net::ERR_CONNECTION_REFUSED
    post @ App.js:11
    toUpperCase @ App.js:29

에러 2
Uncaught (in promise) TypeError: Failed to fetch

profile
pursue nature

0개의 댓글