DOM로 인해 자바스크립트를 사용해 URL, 쿠키, 문서 상호작용으로 발생하는 이벤트 같은 HTML 문서의 모든 특성에 접근이 가능해졌다
웹의 발달로 HTML이 더 많은 리소스를 포함하며, 브라우저 단에서 안전하게 상호작용할 방법이 필요해졌다
참고 : https://www.netsparker.com/whitepaper-same-origin-policy/
어떤 출처에서 불러온 리소스가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 보안 정책. 스크립트에만 적용된다. 동일한 출처의 웹페이지일때만 리소스에 접근하는 것을 허용한다.
예) http://store.company.com/dir/page.html 페이지의 스크립트가 아래 페이지에서 리소스 접근시
어떤 페이지의 악의적인 스크립트가 다른 페이지의 DOM를 통해 데이터에 접근하는 것을 방지한다
이미지, CSS 같은 리소스는 HTML 태그를 통해 다른 출처여도 접근할 수 있다.
⚠️ 사용자를 보호하기 위한 클라이언트 측 정책으로 요청이 들어오면 서버에서는 다른 출처여도 정상적으로 응답하지만 브라우저 단에서 SOP를 확인해 처리한다. 따라서 서버 간 통신에는 적용되지 않는다 ⚠️
SOP가 없을 때 발생가능한 문제 예 :
가짜 은행 피싱사이트의 페이지에 iframe으로 진짜 은행 사이트가 로드됐다. iframe 내 진짜 은행 사이트에 로그인 했을 때 가짜 사이트가 간단한 스크립트로 진짜의 DOM 요소에 접근 가능하다. 요청을 조작해 누군가에게 송금하게 하는것도 가능할 수 있다.
SOP가 없다면 이런 다른 사이트간 요청이 악의적으로 실행될 수 있다
HTTP-header 기반 방식으로 서버가 브라우저에서 리소스 로딩을 할 수 있는 다른 출처를 허용할 수 있게한다
오픈된 웹 환경에서 흔히 있는 다른 출처 간 리소스 사용을 무조건 막을 수는 없다.
따라서 제한된 설정을 통해 부합하는 출처에서 통신을 허용한다
작동방식 :
1) 클라이언트가 다른 출처의 리소스를 요청할 때 헤더에 Origin
필드에 요청을 보내는 출처를 함께 보낸다.
2) 이후 서버가 응답할 때 응답 헤더의 Access-Control-Allow-Origin
필드에 해당 리소스에 접근이 허용된 출처를 보낸다.
3) 응답을 받은 클라이언트는 보냈던 요청의 Origin
과 응답의 Access-Control-Allow-Origin
을 비교해 유효한 응답인지를 결정한다
CORS의 세세한 동작 방식은 Preflight, Simple, Credentialed 3가지 시나리오에 따라 조금씩 다르다
⚠️ 사용자를 보호하기 위한 클라이언트 측 정책으로 요청이 들어오면 서버에서는 다른 출처여도 정상적으로 응답하지만 브라우저 단에서 CORS를 확인해 처리한다. 따라서 서버 간 통신에는 적용되지 않는다 ⚠️
GET, HEAD, POST
중 하나 Accept, Accept-Language, Content-Language, Content-type, DPR, Downlink, Save-Data, Viewport-Width, Width
이외의 헤더를 사용 X application/x-www-form-urlencoded, multipart/form-data, text/plain
만 허용다른 출처 간 통신의 보안을 강화하고 싶을 때 사용
비동기 리소스 요청은 쿠키나 인증 관련 헤더를 별도 옵션 없이 헤더에 담지 않는다. 요청에 인증 관련 정보를 담게 해주는 옵션이 credentials이다
// credentials include 옵션 예시
fetch('https://test.com', {
credentials: 'include',
});
Access-Control-Allow-Origin
에 *
사용 X, URL 명시Access-Control-Allow-Credentials: true
존재참고 : https://evan-moon.github.io/2020/05/21/about-cors/
CORS 처리를 위한 Flask 익스텐션
CORS를 가능하게 하고 싶다면, 모든 곳에서 헤더 상관없이 가능케하는걸 모토로하는 패키지이다
기본설정은 모든 엔드포인트에 모든 origin과 method에 대해 cors를 허용한다
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
@app.route("/api/v1/users")
def list_users():
return "user example"
@app.route("/")
@cross_origin()
def helloWorld():
return "Hello, cross-origin-world!"
참고 : https://flask-cors.corydolphin.com/en/latest/index.html