ssung_항해일지/CS 지식 및 기술면접

CORS란 무엇일까?

ssungcohol 2023. 4. 25. 12:10

CORS란?

  • CORS(Cross-Origin Resource Sharing)는 출처가 다른 자원을 공유한다는 뜻으로, 한 출처에 있는 자원에서 다른 출처에 있는 자원에 접근하도록 하는 개념
  • 직역하면, 교차되는 출차 자원들의 공유를 뜻함
  • 다른 출처에 있는 자원을 요청하면, 이를 교차 출처 요청이라고 부름

교차 출처 리소스 공유(CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제.

웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행


출처란?

https://beomy.github.io/tech/browser/cors/

위의 구성요소 중에서 Protocol + Host + Port 이 세 가지가 같으면 동일 출처(Origin)라고 합니다.

다른 출처 요청일 경우, CORS 정책에 준수하여 요청해야만 정상적으로 응답을 받을 수 있다.


다른 출처 요청의 위험성

<img>, <script>, <frame>, <video>, <audio> 등이 웹에 등장하면서, 페이지 로딩 이후 브라우저에서 이러한 하위 자원들을 가져올 수 있게 되어 동일 출처, 다른 출처 모두 호출이 가능하게 되었다.

 

예를 들어 CORS 정책이 없이 모든 다른 출처 요청이 가능한 브라우저가 있다고 해보자

 

홈페이지를 서핑하고 있는데, <script>가 심어진 evil.com 페이지를 열었다고 생각해보자. 굉장히 유용한 정보를 담고있는 사이트이지만, 페이지를 열면서 <script>가 실행되어 'Delete /account'를 요청하도록 되어있다. Ajax 호출로 은행 API를 출하여 나의 은행 계좌를 삭제해버리는 사고가 발생한다.

 

따라서, 다른 출처의 접근을 막기 위해 동일 출처 정책이 등장한 것이다.


동일 출처 정책 (Same-Origin policy)

  • 다른 출처로부터 조회된 자원들의 읽기 접근을 막아 다른 출처 공격을 예방
  • 그러나, 다른 출처에서 얻은 이미지를 담은 <img>, 외부 주소를 담는 <link> 같은 여러 태그를 허용
  • 동일 출처 정책의 정확한 구현 명세는 없지만 최신의 브라우저들은 일정 규칙을 따른다. (RFC6454)
  • 동일출처 정책은 다른 출처 자원을 가져오는 것을 굉장히 제한적으로 허용
  • SPA와 미더이 중심 웹 사이트들이 더욱 늘어나고 있으므로 관련 규칙들도 계속 늘어남에 따라, 다른 출처 리소스에 접근성을 높이기 위해 CORS가 등장했다

Spring boot에서 cross-origin 설정하기

 

1. 메서드에서 설정하기

@RestController
@RequestMapping("/account")
public class AccountController {
	
    @CrossOrigin
    @RequestMapping(method = RequestMethod.Get, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
    ...
    }
    
    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
	public void remove(@Pathvatiable Long id) {
    ...
    }
}

retrieve() 메서드에 선언된 @CrossOrigin의 기본 설정은 다음과 같다.

1. 모든 출처 허용

2. 허용된 HTTP 메서드는 @RequestMapping 에 선언된 메서드들이다.

3. 프리플라이트 응답은 30분 동안 캐시상태

 

2. 컨트롤러에서 설정하기

@CrossOrigin(origins = "http://Example.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

	@RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
    	...
    }
    
    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
    	...
    }
}

컨트롤러에 설정했으므로 AccountController에 있는 retrieve()와 remove() 함수 모두에 적용된다

 

3. 개별 적용

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public calss AccountController {
	
    @CrossOrigin("http://example.com")
    @RequestMapping(method = RequestMethod.GET, "/{id}")
    public Account retrieve(@PathVariable Long id) {
    	...
    }
    
    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
    	...
    }
}

스프링에서 여러가지 CORS 정책을 복합해서 설정 할 수 있음

모든 메서드들은 3600초가 캐시 시간. retrieve() 메서드는 허용출처가 "http://example.com" 밖에 안된다.

하지만, remove() 메서드는 별도의 설정이 없어 모든 출처가 가능.

 

4. 전역 설정

CORS 정책의 설정은 WebMvcConfigurer를 구현하여 설정이 가능하다.
이는 필터를 기반으로 하여, 전역적으로 모든 요청에 대해서 검사를 하기 때문이다.

@Configuration
@EnableWebMvc
public calss WebConfig implements WebConfigurer {
	
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    	registry.addMapping("/**");
    }
}

참고

https://escapefromcoding.tistory.com/724

728x90