CORS는 왜 발생하는가

홍승보·2023년 1월 23일
0

CORS error는 왜 발생하는가?

  • 웹 개발을 하다보면 아래와 같은 에러를 심심치 않게 마주할 수 있다.

  • CORS error는 동일 출처 정책에 의해서 브라우저가 발생시키는 에러이다.

그럼 SOP(Same-Origin Policy:동일 출처 정책)이란 무엇인가?

  • SOP는 한 Origin(현재 내가 접속해 있는 사이트)에서 로드된 문서나 스크립트가 다른 Origin(다른 사이트)에서 가져온 리소스와 상호 작용하는 것을 제한하는 보안방식이다.
  • 말 그대로 같은 출처에서만 리소스를 공유할 수 있다라는 규칙을 가진 정책이다.

이미지 출처: https://evan-moon.github.io/2020/05/21/about-cors/

SOP는 왜 만들어졌을까?

  • 웹에서 돌아가는 클라이언트 애플리케이션은 사용자의 공격에 너무나도 취약하다.
  • 당장 F12개발자 도구만 켜도 소스코드가 적나라하게 드러나며, 어떤 서버와 어떻게 통신 하는지에 대한 각종 정보들을 무리없이 열람할 수 있다.
  • 만약 SOP정책이 없다면 서로 다른 두 애플리케이션이 마음대로 소통할 수 있는 환경이 된다.
  • 이 말인 즉슨 다른 출처의 애플리케이션에서 악의적인 목적으로 사용자의 정보를 탈취하기가 너무나도 쉬워진다는 것이다.
  • 따라서 같은 출처에서만 리소스를 공유할 수 있다는 규칙(SOP)을 default로 하여 어느정도의 보안적인 이점을 가져갈 수 있다.

출처(Origin)란?

  • 위 설명에서 출처라는 말이 계속 나오고 있다.
  • 출처는 Protocol + Host + Port의 쌍을 말한다.
  • 즉 URL의 맨 앞 3개의 요소인 프로토콜, 호스트, 포트번호가 동일하다면 같은 출처라고 판단하여 SOP정책에 가로막히지 않는다.

이미지 출처: [10분 테코톡] 나붐의 CORS

💡 IE에서는 SOP기준에 두가지 예외사항이 있다. 하지만 위 브라우저는 거의 사용되지 않는 브라우저이므로 참고만 하자.

  1. 신뢰할 수 있는 사이트
  • 양쪽 도메인 모두 높음단계의 보안 수준을 가지고 있을 경우 두 출처가 다르더라도 SOP에 가로막히지 않는다.
  1. 포트
  • 같은 출처라고 판단하는 기준에서 포트를 포함하지 않는다.
  • 따라서 IE에서는 Protocol + Host만 도일하다면 같은 출처로 판단한다.

CORS(Cross-Origin Resource Sharing: 교차 출처 리소스 공유란?)

  • 시대가 발전하면서 많은 애플리케이션들은 내부적으로 동작하기 보다 다양한 다른 애플리케이션이 상호작용하면서 사용자들에게 더욱 편리한 서비스를 제공한다.
  • 즉 서로 다른 출처끼리 리소스를 공유해야 하는 상황이 발생한다.
  • CORS란 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여 하도록 브라우저에 알려주는 체제이다.
  • 즉 정해진 헤더를 통해 다른 출처의 리소스 자원을 공유할 수 있는 방법이다.

CORS는 어떻게 동작할까?

  • 다시 상기하자면 CORS error는 브라우저에서 발생시키는 오류이다.
  • 기본적인 CORS error의 발생과정은 다음과 같다.
  1. HTTP 요청을 하면 브라우저는 요청 헤더에 Origin이라는 필더를 추가한다.
    Origin: 요청을 보낸 출처 (eg. http://naver.com)
  2. 이후 서버는 응답을 내려줄때 응답 헤더에 access-control-allow-origin이라는 필드를 내려준다.
  • access-control-allow-origin : 해당 리소스를 접근할 수 있게 허용된 출처 (eg. access-control-allow-origin:*)
  1. 브라우저는 응답을 반환하기 전에 Origin과 access-control-allow-origin값을 비교하여 유효성을 검증한다.
  • 즉 요청에 대한 응답을 서버가 내려준 후 브라우저 단에서 판단하여 응답을 그대로 반환할지 버릴지 판단하는 것이다.

CORS Error를 해결하는 방법은 뭘까?

  • CORS Error를 해결하는 방법은 크게 3가지가 있다.
  1. 서버에서 access-control-allow-origin설정해주기 ( 정석)
  2. 프론트 프록시 서버 설정을 변경해주기
  3. CORS 기능 끄기 (로컬 개발 시 급할때만 사용)

1. 서버에서 access-control-allow-origin 설정해주기

  • Spring 기준으로 서버에서 CORS 관련 설정하는 방법은 크게 두가지가 존재한다.
  1. @Configuration 설정 방법
  2. @CrossOrigin설정 방법

1. @Configuration 설정 방법

  • 해당 방식은 Configuration 어노테이션을 통해 전역으로 처리하는 방법이다.
// 전역으로 CORS 설정을 할 수 있는 방법
@Configuration
public class CorsFilter implements WebMvcConfigurer {
	@Override
    public void addCorsMappings(CorsRegistry registry){
    registry.addMapping("/api") // 적용할 path 패턴
    		.allowedOrigins("http://localhost:8081") // 허가할 출처들을 기입
            .allowedMethods(	// 허가할 Method 기입
            	HrtpMethod.GET.name,
                HttpMethod.POST.name,
                HttpMethod.PUT.name,
                HttpMethod.DELETE.name
             );
  }

2. @CrossOrigin설정 방법

  • 해당 방식은 모든 도메인이 아닌 특정 도메인에서만 허용할 때 사용하는 방식이다.

  • CORS 설정을 적용시킬 Class 또는 Method위에 @CrossOrigin의 어노테이션을 붙이면 된다.

    @RestController
    @RequiredArgsConstructor
    @RequestMapping("/api")
    @CrossOrigin(origins = {"http://localhost:8080", "http://localhost:9090"}, allowCredentials = "true")
    public class MemberController {
    
      @GetMapping("/hello")
      public String Hello() {
          return "hello";
      }
    }
    
  • 하지만 이 방식은 각각의 Class 혹은 Method마다 선언해줘야 하므로 보통은 1번 방식을 사용한다.

2. 프론트 프록시 서버 설정을 변경해주기

  • 프론트 프록시 서버에서 백엔드 서버간의 출처를 조율해준다.
  • 브라우저와 프론트 프록시 서버는 출처가 동일하므로 CORS error가 발생하지 않는다.

3. CORS 기능 끄기

  • 보안 때문에 프록시와 같은 외부 서버도 못 띄우는 상황이거나 서버의 설정을 기다릴 수 없어 당장 핫픽스 같은 개발을 진행해야 될 때 사용하면 유용하다.
    방법은 아래와 같다.
  1. Chrome 웹스토어에 들어간다. → https://chrome.google.com/webstore
  2. CORS를 검색한다.
  3. 확장프로그램을 다운받는다.

Reference

얄코 - 웹개발 짜증유발자! CORS가 뭔가요?
[10분 테코톡] 나붐의 CORS
https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
https://evan-moon.github.io/2020/05/21/about-cors/#preflight-request
https://velog.io/@beomdrive/CORS-%EA%B7%B8-%EC%86%8D%EC%9C%BC%EB%A1%9C![](https://velog.velcdn.com/images/paul7/post/d6ca6d6d-fb6d-4554-a4df-b149fea9ef9f/image.png)

profile
Junior BE Developer

0개의 댓글