CORS(Cross Origin Resource Sharing)

 

CORS(Cross Origin Resource Sharing)

SOP (Same Origin Policy)

  • 웹애플리케이션 보안모델

  • 브라우저는 스크립트에서 URL 데이터 접근시, Same Origin일 경우에만 허가한다.

https://drek4537l1klr.cloudfront.net/siriwardena/v-2/Figures/image049.png


  • Cross Origin Access 가능한 경우

    • images, stylesheets, scripts, iframes, videos.

  • Cross Origin Access 불가능한 경우

    • data 접근: 예) ajax request


Microservice Architecture & CORS

Same Origin vs. Cross Origin

  • Components of URLs

  • scheme

    • 프로토콜

    • URL 전송 프로토콜 결정

  • hostname

  • port

    • default:[(http,80), (https,443)]

    • default가 아닌 경우 명시해야함

  • Same Origin

    • 처음 로딩한 URL과 [scheme, hostname, port] 가 같다.

  • Cross Origin

    • 처음 로딩한 URL과 [scheme, hostname, port] 가 다르다.


ex) http://www.example.com/dir/page.html

https://en.wikipedia.org/wiki/Same-origin_policy





JSONP (JSONP stands for JSON with Padding.)


SOP 정책을 우회해서 Cross Origin 데이터를 가져오는 방법

예제) https://www.w3schools.com/js/js_json_jsonp.asp


a.com/index.html

<!DOCTYPE html>

<html>

<body>


<h2>Request JSON using the script tag</h2>

<p>The PHP file returns a call to a function that will handle the JSON data.</p>

<p id="demo"></p>


<script>

function myFunc(myObj) {

  document.getElementById("demo").innerHTML = myObj.name;

}

</script>


<script src="demo_jsonp.php"></script>


</body>

</html>



b.com/demo_jsonp.php

<?php

$myJSON = '{"name":"John", "age":30, "city":"New York"}';

echo "myFunc(".$myJSON.");";

?>


b.com/demo_jsonp.php 실행경과 (<script src="demo_jsonp.php"></script>)

myFunc({"name":"John", "age":30, "city":"New York"});

> 스크립트가 실행되면서 데이터를 가져온다.


CORS (Cross Origin Resource Sharing)

CORS는  Cross Origin 데이터에 접근할 수 있는 표준 방법

(JSONP는 SOP 헛점을 이용해  해킹하듯이 데이터를 가져오는 방법)

  • 2004.3: proposed for Voice XML by Matt Oshry, Brad Porter, and Michale Bodell

  • 2006.5: W3C Working Draft

  • 2009.3: renamed "Cross-Origin Resource Sharing"

  • 2014.1: W3C Recommendation


CORS 동작 방법

Cross Origin 데이터에 접근시

브라우저는 Cross  Origin 웹앱에게 데이터 접근 권한을 있는지 물어보고

접근 권한이 있는 경우 데이터를 요청한다.

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

CORS

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS


  • Simple Request

  • Preflighted Requests

  • Credentialed Requests


CORS:Simple Request (GET, HEAD, POST)

한번에 요청 가능

  • browser

    • origin: foo.com

  • server

    • access-control-allow-origin: *

    • access-control-allow-origin: foo.com


CORS: Preflighted Requests (POST, PUT, DELETE)

2단계로 요청: 데이터 변경, 삭제 등의 위험이 있기 때문에 2단계로 처리

  • 1: OPTION 요청으로 접근 권한 요청

  • 2: 요청 [POST]


CORS: Credentialed Requests

  • 인증을 위해 쿠키정보 등의 기밀 사항을 전송해야 하는 경우에 사용

  • server가 "access-control-allow-credentials: true"를 반환하는 경우에만 정상 처리 한다.




Python Example


# open http://localhost:5000

[WebBrowser] --------------------------------> [app1, localhost:5000]


# return index.html

[WebBrowser] <-------------------------------- [app1, localhost:5000]


# xhttp.open("GET", "http://localhost:5001/");

[WebBrowser] <-------------------------------- [app2, localhost:5001]


#case1 

return with header: (Access-Control-Allow-Origin, *)

[WebBrowser] <-------------------------------- [app2, localhost:5001]

[WebBrowser]: OK


#case2 

return without header: header: (Access-Control-Allow-Origin, *)

[WebBrowser] <-------------------------------- [app2, localhost:5001]

[WebBrowser]: ERROR




app1.py

from flask import Flask, escape, request


app = Flask(__name__, static_url_path='/static')



@app.route('/')

def root():

    return app.send_static_file('index.html')



if __name__ == "__main__":

    app.run(host='localhost', port=5000)


app1/index.html

<!DOCTYPE html>

<html>

<body>


<div id="demo">

<h2>Demo: Cross Origin Resource Sharing</h2>

<button type="button" onclick="loadDoc()">request_cors!</button>

</div>


<script>

function loadDoc() {

  const xhttp = new XMLHttpRequest();

  xhttp.onreadystatechange = function() {

    if (this.readyState == 4 && this.status == 200) {

      document.getElementById("demo").innerHTML =

      this.responseText;

    }

  };

  xhttp.open("GET", "http://localhost:5001/");

  xhttp.send();

}

</script>


</body>

</html>



app2.py

from flask import Flask, Response


app = Flask(__name__)



@app.route("/", methods=["GET", "DELETE", "OPTIONS"])

def root():

    print("/")

    res = Response()

    # res.headers.add("Access-Control-Allow-Origin", "*")

    res.set_data("cross origin request response!")

    return res



if __name__ == "__main__":

    app.run(host='localhost', port=5001)



app3.py (cors 라이브러리 이용)

pip install flask_cors


from flask import Flask, Response

from flask_cors import CORS


app = Flask(__name__)

CORS(app)

# CORS(app, resources={r"/api/*": {"origins": "*"}})


@app.route("/", methods=["GET", "DELETE", "OPTIONS"])

def root():

   print("/")

   res = Response()

   res.set_data("cross origin request response!")

   return res



if __name__ == "__main__":

   app.run(host='localhost', port=5001)



CORS: 웹브라우저 기능 끄기


ex) chrome 실행 옵션 추가

--disable-web-security



CORS vs. JSONP

  • CORS > JSONP

    • JSONP는 GET만 지원

    • JSONP는 해킹 또는 꼼수 느낌, CORS는 당당히 XMLHttpRequest로 처리

    • XSS(cross-site-scripting) 공격에 취약점

      • 크로스 도메인이 해커에 의해 공격당했을 경우, 결과 데이터가 원하지 않는 스크립트를 실행할 수 있음

      • 이에 반해 CORS는 데이터 파싱을 직접 하기 때문에 공격당할 가능성이 상대적으로 적음.

  • CORS < JSONP

    • 레거시 브라우저 (IE9, Opera Mini 등의 오래된 브라우저)에서 동작 가능

댓글

이 블로그의 인기 게시물

install tensorflow gpu version on macbook pro

Neural Machine Translation