CORS(Cross-Origin Resource Sharing)는 웹 페이지가 다른 도메인의 리소스에 접근할 때 보안을 위해 특정 규칙을 적용하는 방식입니다. 이때 요청은 Simple Request(단순 요청)과 Non-Simple Request(비단순 요청)으로 나뉩니다.
1. Simple Request (단순 요청)
단순 요청은 브라우저에서 서버에 사전 요청(preflight) 없이 바로 요청을 보낼 수 있는 CORS 요청 유형입니다. 사전 요청이 없기 때문에 네트워크 자원이 절약되고, 단순한 API 호출이나 기본 리소스 접근에 사용됩니다.
Simple Request의 조건
1. 허용된 HTTP 메서드:
• GET
• POST
• HEAD
2. 허용된 요청 헤더:
• 추가적인 사용자 정의 헤더를 사용할 수 없으며, 아래 헤더만 허용됩니다:
• Accept
• Accept-Language
• Content-Language
• Content-Type (단, 특정 값만 허용됨)
3. 허용된 Content-Type 값:
• Content-Type 헤더의 값이 아래 중 하나여야 합니다:
• text/plain
• multipart/form-data
• application/x-www-form-urlencoded
이 세 가지 조건 중 하나라도 충족하지 않으면 요청은 비단순 요청으로 간주됩니다.
Simple Request의 예시
예시 1: GET 요청
다음 GET 요청은 Simple Request에 해당하며, 사전 요청 없이 서버에 접근합니다.
fetch("https://api.example.com/data", {
method: "GET",
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
예시 2: POST 요청 (Content-Type: application/x-www-form-urlencoded)
fetch("https://api.example.com/submit", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: "key1=value1&key2=value2"
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
위 요청은 조건을 충족하기 때문에 사전 요청 없이 바로 서버에 전달됩니다.
2. Non-Simple Request (비단순 요청)
Non-Simple Request는 단순 요청의 조건을 충족하지 않는 모든 요청입니다. HTTP 메서드가 PUT, DELETE, PATCH 등 단순 요청에 해당하지 않는 경우이거나, 허용되지 않은 헤더가 포함된 요청은 비단순 요청으로 처리됩니다.
Non-Simple Request의 조건
1. 허용되지 않은 HTTP 메서드 사용:
• PUT, DELETE, PATCH, OPTIONS, 등 단순 요청에 포함되지 않은 메서드를 사용할 경우
2. 허용되지 않은 헤더 포함:
• 사용자 정의 헤더나 인증 관련 헤더(Authorization 등)가 포함된 경우
3. 허용되지 않은 Content-Type 값 사용:
• application/json, application/xml, text/xml 등 단순 요청에서 허용되지 않은 Content-Type 값이 포함된 경우
Non-Simple Request의 사전 요청 (Preflight Request)
비단순 요청을 보내기 전에, 브라우저는 **사전 요청(preflight request)**이라는 OPTIONS 메서드를 서버에 먼저 보냅니다. 서버는 이 사전 요청을 통해 클라이언트가 보낸 본 요청을 허용할지 결정합니다.
• 사전 요청에는 HTTP 메서드와 헤더 등 본 요청의 정보를 포함하여 서버가 허용 여부를 판단할 수 있도록 합니다.
• 서버는 사전 요청에 대해 Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Origin 등의 헤더로 응답하며, 이를 통해 본 요청 허용 여부를 클라이언트에 전달합니다.
예시 1: 사전 요청 후 본 요청
1. 사전 요청 (OPTIONS):
• OPTIONS 메서드로 Authorization 헤더가 포함된 POST 요청을 보내기 전, 사전 요청을 먼저 보냅니다.
OPTIONS /secure-data HTTP/1.1
Host: api.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization
Origin: https://client.example.com
2. 서버 응답 (허용하는 경우):
• 서버가 응답으로 요청을 허용하는 헤더를 설정합니다.
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://client.example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization
3. 본 요청:
• 서버가 사전 요청을 허용했다면, 이제 클라이언트는 본 요청을 POST로 보내며 Authorization 헤더를 포함할 수 있습니다.
fetch("https://api.example.com/secure-data", {
method: "POST",
headers: {
"Authorization": "Bearer token",
"Content-Type": "application/json"
},
body: JSON.stringify({ key: "value" })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
CORS Simple Request vs. Non-Simple Request 요약
요청 유형 | 조건 | 사전 요청 필요 여부 |
---|---|---|
Simple Request (단순 요청) |
|
아니요 |
Non-Simple Request (비단순 요청) |
|
예 |
참고: Simple Request는 서버에 직접 요청할 수 있지만, Non-Simple Request는 서버 권한 확인을 위한 사전 요청(OPTIONS)이 필요합니다.
이렇게 CORS는 클라이언트가 다른 출처의 리소스에 접근할 때 서버에서 명시적으로 허용하는 경우에만 접근을 허용하도록 해 보안을 강화하고 있습니다.
'Spring Security' 카테고리의 다른 글
RFC6265 (0) | 2024.10.31 |
---|---|
SameSite (0) | 2024.10.31 |
Spring Security 인증 아키텍처 (0) | 2024.10.31 |
FilterOrderRegistration 클래스 구조와 역할 (0) | 2024.10.31 |
requestMatcher (0) | 2024.10.30 |