Cors란...

SaGo_MunGcci·2022년 8월 13일
0

스프링

목록 보기
22/31
post-thumbnail

Definition Access

CORS란?

CORS는 Cross-Origin Resource Sharing의 약자로 직역하면 "교차 출처 리소스 공유" 이다.

좀 더 쉽게 말하면 동일한 출처가 아닌 다른 출처에서 데이터를 주고 받는 것을 허용하는 정책이다.


이미지 출처 : https://antstudy.tistory.com/259



Mechanism

CORS는 왜 필요한가?

  • CORS가 없이 모든 곳에서 데이터를 요청할 수 있게 되면, 다른 사이트에서 원래 사이트를 흉내낼 수 있게 된다.

  • 예를 들어서 기존 사이트와 완전히 동일하게 동작하도록 하여 사용자가 로그인을 하도록 만들고, 로그인했던 세션을 탈취하여 악의적으로 정보를 추출하거나 다른 사람의 정보를 입력하는 등 공격을 할 수 있다.

  • 공격을 할 수 없도록 브라우저에서 보호하고, 필요한 경우 에만 서버와 협의하여 요청할 수 있도록 하기 위해서 필요하다.

그렇다면 이러한 정책이 왜 필요한 것일까?

그건 먼저 "동일 출처 정책"에 대해서 알아야 한다.

SOP(Same Origin Policy 동일 출처 정책)

  • SOP는 Same Origin Policy의 줄임말
    • 다른 출처의 리소스를 사용하는 것에 제한하는 보안 방식
      --> 해커가 다른 출처의 리소스로 요청을 한다면, Cross Origin(다른 출처)라고 판단하고 요청을 거부한다.

출처(Origin)란?

  • 서버의 위치를 의미하는 https://google.com과 같은 URL 들은 마치 하나의 문자열 같아 보여도,사실은 여러 개의 구성 요소로 이루어져 있다.
    (Restful Api와 연결되는 부분이다.)

  • 즉, 서버의 위치를 찾아가기 위해 필요한 가장 기본적인 것들을 합쳐놓은 것이다.

  • URL의 Protocl, Host, Port를 통해 같은 출처인지 다른 출처인지 판단할 수 있다.
    --> Protocol, Host, Port 무엇이라도 다르면, 다른 출처라고 판단한다.
    출처 내의 포트 번호는 생략이 가능한데, 이는 각 웹에서 사용하는 HTTP, HTTPS 프로토콜의 기본 포트 번호가 정해져 있기 때문이다.

잠깐!

http://localhost와 동일 출처인 url은 무엇일까?

  1. http:// localhost:80
  1. http://localhost/api/cors

    • /api/cors 는 추가적으로 붙는 location 이기 때문에 api 앞에까지 비교를해서 동일 출처로 본다.
  2. 그러면 http://127.0.0.1는?
    - 127.0.0.1 은 localhost가 맞기는 한데 브라우저 입장에서는 String value를 서로 비교한다.
    => 결국 String value가 다르기 때문에 브라우저는 다른 출처로 본다.

실무 예를 들어보자.

보통 프론트엔드 개발자가 React와 같은 라이브러리를 사용해서 개발하는 경우 백엔드 서버와 별도의 프론트 서버가 존재한다.

프론트 개발을 할때, 로컬의 백엔드 서버에 연동하거나 개발 서버에 연결해서 API 연동을 하는데 만일 다음과 같이,

프론트 서버의 URL이 http://localhost:3000이고, 백엔드 서버가 http://localhost:8080에 띄워져 있다고 하면

이때 프론트 서버와 백엔드 서버는 다른 출처 (Origin)으로써 Same-Origin Policy 정책을 어긋나기 때문에, 서버로부터 응답이 넘어올 때 브라우저에서 CORS Policy 오류를 발생시키게 된다.

출처: https://inpa.tistory.com/entry/WEB-📚-CORS-💯-정리-해결-방법-👏 [👨‍💻 Dev Scroll:티스토리]

그렇다면 다른 출처의 리소스가 필요하다면 어떻게 할까?

=> 이때 필요한 게 CORS이다.

CORS란?

  • Cross-Origin Resource Sharing의 줄임말이다.

    • => 다른 출처의 자원을 공유하는 것
      교차 출처 리소스 공유(CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 정책이다.
  • 그렇다면 CORS는 어떻게 안전하게 다른 출처와 리소스를 공유하는 것일까?

  • 바로 두 가지 방법이 있는데, 단순 요청 방법과 예비 요청 방법이 있다.

요청 방법은 요청하는 헤더와 응답하는 헤더를 통해서 이루어 진다.

요청 헤더

  1. Access-Control-Request-Method
    -요청을 할 때 어떤 메서드를 사용할 것인지를 알려주는 것이다.

  2. Access-Control-Request-Headers
    -요청을 할 때 어떤 헤더를 사용할 것인지 알려주는 것이다.

응답 헤더

  1. Access-Control-Allow-Origin
    -리소스에 접근할 수 있도록 허용하는지를 알려주는 것이다.

  2. Access-Control-Expose-Headers
    -브라우저에게 접근할 수 있는 리스트들을 알려주는 것이다.

  3. Access-Control-Max-Age
    -캐싱되는 시간을 알려주는 것이다.

  4. Access-Control-Allow-Credentials
    -크레덴셜이 true일 때 요청할지에 대한 것을 알려주는 것이다.

  5. Access-Control-Allow-Methods
    -허용되는 메서드를 알려주는 것이다.

  6. Access-Control-Allow-Headers
    -사용 가능한 HTTP 헤더를 알려주는 것이다.

  • 이제 헤더에 대해 알아 보았으니 본격적으로 요청에 대해 다뤄보도록 하자.

Preflight Request (예비 요청)

  • 예비 요청은 말 그대로 미리 요청을 보내보고, 안전한지를 판단한 뒤에 본격적으로 요청을 하는 방식이다.

  • 아래와 같이 예비 요청을 보내고 그에 대한 응답을 받은 뒤 실제 요청을 보내고 응답받게 된다.

  • 조금 더 구체적으로 말하면 헤더에 Access-Control-Request-Method를 통해 요청하는 HTTP 메서드 GET,POST,PUT,DELETE 중 하나의 메서드와 Access-Control-Request-Headers를 통해 OPTIONS라는 헤더를 넣고 요청을 보낸다.

  • 이 때 예비로 확인하는 것 뿐이기 때문에 바디에 아무것도 작성하지 않고 헤더만 보낸다.

  • 해당 메서드와 헤더가 유효하다면 서버는 응답 헤더를 통해 접근 가능한지(Access-Control-Allow-Origin), 사용할 수 있는 리소스의 리스트(Access-Control-Expose-Headers), 캐싱 되는 시간(Access-Control-Max-Age) 등을 알려주는 것이다.

Simple Request (단순 요청)

  • 단순 요청은 위의 예비 요청과는 달리 서버에 바로 본격적으로 요청을 시작한다.

  • 그렇다면 미리 확인하지도 않고 어떻게 안전하게 리소스를 요청하는 것일까?

  • 그 방법은 조금 까다로운 조건들을 거는 것이다.

  1. Access-Control-Request-Method를 통해 요청할 때 메서드는 HTTP 메서드가 아닌 GET,HEAD,POST 중 하나여야 한다.
  1. Access-Control-Request-Headers 통해 요청을 보낼 때 Accept Accept-Language,Content-Language, Content-TypeDPR, Downlink, Save-Data, Viewport-Width 중 하나여야 한다.
  1. Content-Type을 사용할 경우 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나여야 한다.
  • 이렇게 까다로운 조건을 걸고 해당 조건에 부합하다면 안전한 요청이라 인식하고 데이터를 응답하는 형식이다.

코드 적용

  • WebMvcConfigurer implements하는 WebConfig를 만들어서
  • 전체적으로 적용가능
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {

        corsRegistry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .exposedHeaders("*")
                .exposedHeaders("Authorization","Refresh-Token")
                
                .maxAge(3000);


    }
  • 해당 컨트롤러만 Cors허용.
@Slf4j
"@CrossOrigin"
@RequiredArgsConstructor
@RestController
public class CGVInfoController {

    //private static Logger logger = LoggerFactory.getLogger(CGVInfoController.class);

    private final CgvInfoService cgvInfoService;
    
    
    ...
    

참고 : https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
참고 : https://antstudy.tistory.com/259
참고 : https://fomaios.tistory.com/entry/Network-CORS%EB%9E%80-feat-%EB%B3%B4%EC%95%88HTTP



Retrospection

  • 굉장히 복잡한데 CSRF,XSS를 공부하면서 복잡한 만큼 우리에게 반드시 필요하니까 사용하는 것이다.

  • 꾸준히 읽고 이해하고 공부하자.



profile
이리저리 생각만 많은 사고뭉치입니다.

0개의 댓글