새로운 내용을 공부할 때
새로운 내용의 공부를 시작할 때 용어의 정의를 이해하지 못하거나 정확하게 알지 못한다면 그 용어가 포함된 문장을 이해하지 못합니다.
작은 단어 하나가 내용을 이해하지 못하게 하기 때문에 용어를 정확하게 이해하는 것이 중요합니다.
SOP와 CORS
목표 D-day : 42 일
학습목표Permalink
- SOP 알기
- CORS 알기
SOP 배경Permalink
은행 웹사이트에서 로그인에 성공하여 인증된 사용자라면 서버에서 쿠키에 인증 정보를 저장합니다.
현재 은행에 접속한 상태에서 출금 페이지에 접근할 때 인증 정보를 통해서 인가에 성공하고 개인 정보를 확인할 수 있습니다.
쿠키는 브라우저내에 저장되는 정보로 쿠키에 설정된 KEY(도메인)
이 동일할 경우 쿠키 정보를 자동으로 전달하는 규칙이 있습니다.
만약 피싱 사이트에 모르고 접속하면 피싱 사이트 접속한 경우 피싱 사이트 내 코드에서 링크나 폼을 통해 은행 사이트에 요청을 보내면 브라우저는 KEY
를 확인하고 은행 인증 쿠키를 전달하게 됩니다.
이때 피싱 사이트에서 전달하는 과정에서 정보를 누출하여 개인정보를 빼갈수 있습니다.
따라서 이런 위험을 줄이기 위해 HTTP에서 보내는 사람의 정보가 서버와 동일하지 않을 경우 SOP에 의해 오류가 발생됩니다.
SOPPermalink
정의Permalink
SOP는 Same-Origin Policy
로 동일한 출처 정책입니다. 은행 사이트에 로그인을 하고 다른 기능을 이용하려면 동일한 사이트내에서만 요청과 응답을 양방향에서 가능하도록 하는 보안 정책입니다.
예를 들어 국민 은행 사이트에 로그인을 한 뒤, 국민은행 사이트에서 국민은행 출금, 적금, 이체등은 가능합니다. 하지만 국민카드에서 국민은행의 정보를 가져오려고하면 출처가 다르기 때문에 요청을 브라우저에서 거부합니다.
출처Permalink
출처(Origin
)은 검색엔진 주소를 클릭하면 보이는 모든게 출처입니다.
https://www.naver.com
이라고 나온다면 https
는 프로토볼, www.naver.com
도메인, 443
https 포트번호
이 세가지를 가르켜 출처라고 합니다.
다른 출처Permalink
http://www.naver.com != https://www.naver.com
: 프로토콜이 다른경우, 포트가 다른경우
https://www.naver.com != https://www.daum.net
: 도메인이 다른 경우 다른 출처입니다.
목적Permalink
이 SOP로 같은 사이트 내에서 상호작용(서로 요청과 응답)이 가능하지만 다른 출처에서 민감한 데이터를 접근하거나 링크를 통해서 요청이 가지 않도록 하는 방식입니다.
한계Permalink
SOP는 보안에 초점이 되어있습니다. 하지만 합법적인 경우에도 클라이언트와 서버 간의 다른 출처에서 리소스를 공유하는데 발생할 수잇습니다.
예를 들어:www.naver.com
에서 온라인 결제를 위해 계좌 이체 기능을 사용하기 위해 www.bank.com
에 요청을 보내야하지만 SOP로 인해 요청이 전송되지 않습니다.
CORSPermalink
정의Permalink
CORS는 다른 출처의 리소스를 요청할 수 있도록 허용하는 매커니즘입니다.
서버가 다른 출처
를 허용하면 허용된 출처와 동일한 출처만 등록할 수 있도록 하는 방식입니다.
콘서트장에 가면 특정 입구는 관리자 외 출입 금지라고 적혀있습니다.
관리자로 등록이 되었다면 자유롭게 이동할 수 있습니다.
작동원리Permalink
브라우저는 서버에 먼저 OPTIONS
메서드를 사용해 사전 요청(Preflight 요청)을 보냅니다
이 요청에는 어떤 도메인, 메서드(GET
,POST
등), 그리고 헤더를 사용할지에 대한 정보를 보냅니다.
OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.example
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
-
요청 메서드는 항상
OPTIONS
를 보냅니다. -
Origin
은 요청이 발생된 출처(도메인)을 나타냅니다. 이 출처가 서버에서 허용된 출처인지 확인하는데 사용합니다.Access-Control-Request-Method: 클라이언트가 이후 실제 요청에서 사용할 HTTP 메서드입니다(예:
POST
,PUT
등).Access-Control-Request-Headers: 실제 요청에서 사용할 커스텀 헤더들이 명시됩니다(예:
Content-Type
,Authorization
등).
서버는 Preflight가 오면 아래와 같이 응답을 합니다.
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
- 응답 코드는 200,204 둘 다 허용됩니다.일부 브라우저는 204 No Content는 아래와 같이 이해를 할 수 있습니다.
Preflight 요청은 이 요청을 보내도 괜찮을 까요 ? 사전 확인 요청입니다
204 No Content로 응답하는 경우 일부 브라우저는 해당 리소스(
/resources/post-here/
)에 데이터가 없구나 생각하고실제로 보내야하는
POST
요청을 보내지 않을 수 있습니다.
따라서 Preflight요청은 가능하면 200 OK
명확한 상태 코드를 사용하는 것이 좋습니다.
- 출처 : MDN-OPTIONS
이후 응답이 OK가 된다면 클라이언트는 실제 데이터를 요청할 수 있습니다.
만약 응답이 OK가 아니라면 브라우저는 요청을 차단합니다.
서버 진영Permalink
서버는 CORS에 허용할 메서드, Header, Origins를 설정합니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://foo.example")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
Preflight 요청 최적화Permalink
사전 요청은 자주 발생하면 성능에 영향을 줄 수 있기 때문에, CORS 관련 응답 헤더에 Access-Control-Max-Age
를 통해 일정시간동안 사전 요청을 캐싱할 수 있습니다.
registry.addMapping("/**")
.allowedOrigins("https://foo.example")
.allowedMethods("GET", "POST")
.maxAge(3600); // 1시간 동안 캐싱
CORS에서 인증 정보를 받으려면Permalink
registry.addMapping("/**")
.allowedOrigins("https://foo.example")
.allowedMethods("GET", "POST")
.allowCredentials(true);
CORS 요청이 쿠키, 인증 토큰 등을 포함할 때는 Access-Control-Allow-Credentials
을 true
로 설정해야합니다.
그리고 허용하는 Origins는 반드시 특정 도메인을 지정해야합니다 *
불가
정리Permalink
- CORS 설정을 너무 느슨하게 하면 나쁜 웹사이트나 스크립트가 무단으로 서버에 접근할 수 있습니다.
- 캐싱 최적화를 통해 사전 요청을 최소화할 수 있습니다.
- 특정 도메인을 허용하거나, 환경별로 CORS를
application.properties
등으로 구분하여 사용할 수 있습니다.
클라이언트 측Permalink
클라이언트도 CORS로 인증 정보를 전달해야할 때 아래와 같이 설정으로 정보를 전달할 수 있습니다.
axios.get('https://api.example.com/data', {
withCredentials: true
});
댓글남기기