ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CORS 이해하기 및 해결방법
    Frontend/Javascript 2022. 12. 21. 20:48
    CORS

    Cross-Origin Resource Sharing

     

    여기서 출처(Origin)란, URL 구조에서 Protocal, Host, Port를 합친 것을 말한다.

    https://tistory.com/ 를 기준으로 Protocal은 'https//' , Host는 'tistory.com' , Port는 https의 번호인 443을 나타낸다.

     

    동일 출처 정책을 지키면 외부 리소스를 가져오지 못하지만 XSS나 XSRF 등의 보안 취약점을 노린 공격을 방어할 수 있다.

    Same origin 정책과 cross origin 정책은 아래와 같다.

     

    - Same origin 정책

    Client와 Server가 동일한 IP주소에서 동작하고 있다면 별다른 제약없이 서로 주고받을 수 있다.

    - Cross origin 정책

    하지만 클라이언트가 서버와 다른 IP에 있다면 원칙적으로는 그 어떤 데이터도 주고받을 수 없다.

     

    그래서 client와 서버가 다른 도메인에 있을 때 데이터를 주고 받기 위해 서버단에서 client에게 response를 보낼 때

    Access-Control-Allow-Origin이라는 부분을 헤더에 추가를 해줘야 서버가 다른 IP주소에서의 요청도 허용한 것이므로 데이터를 받을 수 있다.

     


    그래서 기본적으로는 다른 ip에서는 data sharing이 불가능하다.

    하지만 외부 리소스를 참고는 상황에 따라 꼭 필요한 경우가 있다.

    외부 리소스를 사용하기 위한 동일 출처 정책의 예외 조항이 CORS이다.


    그렇다고 Cross origin 정책에 따라 외부 리소스를 아예 가지고 오지 못하는 것은 아니다.

    1. (Server) 서버 단에서 허용해주기

    Springboot에서는 API Controller단에 허용하려는 API위에 @CrossOrigin(origins = "", allowedHeaders = "")

    Annotation을 통해 클라이언트에게 데이터를 전달할 수 있다.


    2-1. (Client) 웹 브라우저에서 동일 출처 정책 비활성화 - 브라우저 설정 변경

     

    동일 출처 정책은 브라우저에서 임의로 하는 것이기 때문에 브라우저에서 동일 출처 정책을 사용하지 않으면 된다.

    Chrome의 바로가기에서 마우스 오른쪽을 누르고 대상 경로에 아래와 같은 명령어를 추가해주면 된다.

    해당 명령어는 Chrome의 web security를 비활성화하는 것이다. 

     

    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --disable-gpu --user-data-dir=~/tmp

    "C:\Program Files ~... "는 사용자의 경로이고, --user-data-dir는 Chrome에서 발생할 user data의 저장 폴더를 지정해주면 된다.

     

    2-2. (Client) 웹 브라우저에서 동일 출처 정책 비활성화 - Chrome 확장 프로그램 이용

    Chrome의 웹 스토어에서는 이와 같은 문제를 해결하기 위한 확장 프로그램을 제공한다.

    'cors'를 검색하여 'Allow CORS: Access-Control-Allow-Origin' 를 설치해주면 된다.


    3. (server, client) jsonp 방식으로 json 데이터 가져오기 -> 보안상의 이슈로 이제 사용되지 않음.

    • 자바스크립트 파일이나 css 파일은 동일 출처 정책에 영향을 받지 않고 가져올 수 있다.
    • 이를 이용해서 자바스크립트 파일을 가져와서 이를 json 형식으로 파싱해서 데이터를 사용할 수 있다.
    // 서버에서 내려줌
    myCallback({
      title : 'hello world!'
    })

    우리가 가져오려는 <script> 태그는 결과물 자체를 변수에 저장할 수 없기 때문이다.

    서버에서는 단순히 Json데이터를 내려주는 게 아니라 myCallback()으로 감싸서 내려줘야한다.

    브라우저에서는 서버에서 내려준 콜백함수가(myCallback) 미리 html에서 정의가 되어 있어야 한다.

     

    // 브라우저
    <script>
    function myCallback(json){
       window.result = json;
    }
    </script>
    <script src="https://test.com"></script>
    // 아래와 같이 callback 함수의 내부가 변환됨.
    myCallback({
       title : 'hello world!'
    })

    이런식으로 서버에서 내려준 json 데이터를 콜백함수를 통해서 브라우저의 전역변수인 window객체에 넣어서 사용할 수 있어 이를 파싱하여 사용할 수 있다.

     

    이러한 방법은 CORS가 2009년에 나오기전까지 사용되던 방법인데 이제는 보안상의 이슈로 더이상 사용되지 않는다고 한다.

     

    참고 :

    https://velog.io/@qortmdalsdl/CORS-%EC%A0%95%EB%A6%AC%EC%99%80-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-Chrome

    https://ngio.co.kr/9615

    https://simsimjae.medium.com/cors%EC%99%80-jsonp%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-aa3ec0456e97

Designed by Tistory.