Contents
CORS 정책이란?CORS 정책이란?
CORS(Cross-Origin-Resource-Sharing) 교차 출처 리소스 공유 정책은 웹 브라우저가 다른 출처(도메인, 프로토콜, 포트)의 리소스를 요청할 수 있도록 허용하는 보안 기능.
이는 동일 출처 정책(SOP - Same-Origin-Policy)의 제한을 완화하기 위해 사용된다. 동일 출처 정책은 악의적인 웹사이트가 사용자의 데이터를 훔치는 것을 방지하기 위해 도입된 보안 조치이다.
하지만, 이러한 제한은 정당한 교차 출처 요청에도 적용되어 웹 애플리케이션의 유연성을 떨어뜨릴 수 있다. 이를 해결하기 위해 CORS가 사용된다.
동일 출처 정책 (SOP 정책)?
- 동일 출처란 프로토콜, 호스트, 포트가 모두 같은 경우를 말한다.
- 즉,
http://localhost.com
과http://localhost.com:80
은 동일 출처로 간주함. 그러나http://localhost.com
과https://localhost.com
은 다른 출처이다.
- 동일 출처 정책은 브라우저가 동일 출처가 아닌 리소스에 대한 요청을 차단하도록 한다.
요청의 종류
CORS 요청은 크게 두 가지로 나뉜다.
- 단순 요청(Simple Request):
- GET, POST, HEAD 메서드 중 하나를 사용
- 커스텀 헤더를 포함하지 않는다
- Content-Type은
application/x-www-form-urlencoded
,multipart/form-data
,text/plain
중 하나여야 한다.
- 단순 요청의 경우, 브라우저는 요청을 보내기 전 preflight 요청을 보내지 않는다.
- 프리플라이트 요청(Preflight Request):
- 단순 요청의 조건을 충족하지 않는 요청
- OPTIONS 메서드를 사용하여 서버가 실제 요청을 허용하는지 확인하는 요청을 먼저 보낸다.
- 브라우저는 preflight 요청을 보내고, 서버가 허용하는 경우에만 실제 요청을 보낸다.
BoardController
@GetMapping("/test/page") public @ResponseBody String page(){ return "page"; } @CrossOrigin(origins = "http://127.0.0.1:5500") // 모든 도메인 허용 (위험함) 프론트쪽 서버만 허용해 주어야 한다 @GetMapping("/test") public @ResponseBody String test(){ return "ok"; }
test.mustache
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>page</h1> <hr> <script> async function download(){ let response = await fetch("http://localhost:8080/test"); let body = await response.text(); console.log(body); } download(); </script> </body> </html>
vscode
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>page</h1> <hr> <script> async function download(){ let response = await fetch("http://localhost:8080/test"); let body = await response.text(); console.log(body); } download(); </script> </body> </html>
브라우저는 모든 정보가 도메인 별로 관리된다
크로스오리진은 자바스크립트시에만 공격
크로스오리진은 도메인이 다름
ip만 달라도 도메인이 다름
포트만 달라도 도메인이 다름
둘다 같아야 도메인이 같다고 함
웹에서의 대부분의 공격은 자바스크립트 공격
공격이 들어오면 막는다
이것을 설정해주는 것은 서버
서버가 필터를 걸어 놓는다
필터에다 특정 ip만 허용하고 나머지는 차단
컨트롤러에 걸면 복잡해진다
그래서 필터에 걸어둔다
포스트맨은 자바스크립트 요청이 아니기 때문에 요청이 가능
앱은 자바로 만들기 때문에 요청 가능
리액트는 자바스크립트로 만들어졌기 때문에 요청 거부
플러터로 웹으로 빌드 시키면 자바스크립트로 컴파일 되기 때문에 요청 거부
CORS 에러 해결 방법
- 서버 측에서 허용 설정: 서버가 적절한 CORS 헤더를 포함하도록 설정
- 프록시 서버 사용: 동일 출처 정책을 우회하기 위해 프록시 서버를 설정
- JSONP 사용: GET 요청에 한해 JSONP를 사용해 CORS 문제를 해결할 수 있다. 하지만 이는 POST, PUT, DELETE 요청에서는 사용 불가.
Share article