Codestates SEB FE 42기/정리노트

S2 unit10 | web server : SOP, CORS

2realzoo 2022. 12. 14. 10:52

📌 SOP (Same-Origin Policy : 동일 출처 정책)

: 같은 출처의 리소스만 공유 가능

=> 잠재적으로 해로울 수 있는 문서를 분리하여 공격 경로를 줄여줌

 

동일 출처 정책의 출처란?

: 프로토콜, 호스트, 포트로 구성

 

📌 CORS (Cross-Origin Resource Sharing : 교차 출처 리소스 공유)

: 추가 헤더를 사용하여 다른 출처 리소스에 접근할 수 있는 권한을 부여하도록 브라우저에게 알리는 체제

 

CORS의 동작 방식

1. 프리플라이트 요청 (Preflight Request)

: 실제 요청을 보내기 전, OPTIONS 메소드로 사전 요청을 보내 해당 리소스에 접근 권한이 있는지 확인하는 것

  • 실제 요청을 보내기 전, 미리 권한 확인을 할 수 있기 때문에 리소스 면에서 효율적임
  • CORS에 대비되어 있지 않은 서버를 보호할 수 있음

➰ CORS 이전에 만들어진 서버들은 요청을 우선 처리하고 응답을 보내기 때문에 프리플라이트 요청을 하지 않고 실제 요청을 먼저 보낸다면 서버에 악영향을 미칠 수 있음

 

 

2. 단순 요청 ( Simple Request)

: 특정 조건을 만족하면 프리플라이트 요청을 생략

 

조건

  •  GET, HEAD, POST 메서드 사용
  • Accept, Accept-Language, Content-Language, Content-Type 헤더의 값만 수동으로 설정 가능
    • Content-Type 헤더:  application/x-www-form-urlencoded , multipart/form-data , text/plain 값만 허용

 

3. 인증정보를 포함한 요청 (Credential Request)

: 요청 헤더에 인증 정보를 담은 요청

 

프론트

: 요청 헤더에 withCredentials : true 포함

 

withCredentials : true

: 요청에 credential 정보 담아서 보낼지 결정하는 항목

 

➰ credential 정보가 포함된 요청

  • 쿠키를 첨부해서 보내는 요청
  • 헤더에 Authorization 항목이 있는 요청

 

 

서버

: 응답 헤더에 Access-Control-Allow-Credentials : true 포함

Access-Control-Allow-Origin 을 와일드카드(*)로 설정하고 credential과 함께 사용하면 오류 발생         

 

Access-Control-Allow-Origin

: 접근 가능한 Origin 나타냄

 

Access-Control-Allow-Credentials : true

: 요청의 자격증명 모드(Request.credentials)가 "include" 일때, 브라우저들이 응답을 프론트엔드 자바스트립트 코드에 노출할지 결정하는 항목

 


📌 CORS 설정 방법

1. Node.js 서버

const http = require('http');

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

// 특정 도메인
  response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");

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

 

2. Express 서버 (cors 미들웨어 사용)

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

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

//특정 도메인
const options = {
  origin: "http://localhost:3000", // 접근 권한을 부여하는 도메인
  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" });
});