CORS(Cross Origin Resource Sharing, 크로스 도메인) 이슈

최근 케이블 통신사와  클라우드 서버간 연동 과정에서 CORS(Cross Origin Resource Sharing, 크로스 도메인) 이슈가 발생했다.

케이블 통신사에서는 STB의 기능들이 브라우저에서 동작하기 때문에 우리가 구축한 서버에 연동을 위해서는 CORS가 우리 서버에서 허용이 필요하다는 의견을 줬다.

그래서 CORS가 무엇인지 확인하고, 보안 이슈가 없는지 등을 검토 해 봤다.

CORS(Cross-Origin Resource Sharing)란 무엇인가?

CORS는 한 도메인에서 로드되어 다른 도메인에 있는 리소스와 상호 작용하는 클라이언트 웹 애플리케이션에 대한 방법을 정의한다

최신 웹 브라우저들이 보안상의 이유로 JavaScript나AJAX로 외부 Host로 접속하는 것을 차단하기 시작했다. 그래서 JavaScript는 보안 측면에서 Same Origin Policy 정책을 둬서 자신이 속한 동일 도메인내에서만 서버 요청을 허용하고, 다른 도메인의 서버 요청을 차단한다.

이 문제를 해결하기 위해 CORS가 제안 되었으며, AWS 등 많은 Public Cloud에서도 지원하기 시작했다.

CORS 표준은 브라우저와 서버에 그들이 권한을 가진 원격 URL을 요청할 수 있는 방법을 제공하는 새로운 HTTP 헤더를 설명한다. 일부 유효성 검사 및 권한 부여는 서버에서 수행 할 수 있지만 일반적으로 이러한 헤더를 지원하고 부과하는 제한 사항을 준수하는 것은 브라우저의 책임이다. 

CORS의 종류는 4가지가 있다.
  1. Simple Request
  2. Preflight Request
  3. Credential Request
  4. Non-Credential Request

Simple Request

Simple Request는 세 가지 조건이 있다.
  1. GET, HEAD, POST 중 한 가지 방식을 사용해야 함
  2. POST일 경우 Context-type이 아래 셋 중 하나를 만족
    1. application/x-www-form-urlencoded
    2. multipart/form-data
    3. text/plain
  3. Custom Header를 전송하지 않아야 함

Preflight Request

Preflight Request는 먼저 Preflight 요청을 보내서 서버가 응답을 하는지 확인 한다. Preflight 요청은 OPTION 메소드를 사용한다. 

[Request]
OPTIONS /
Host: service.example.com
Origin: http://www.example.com

[Respose]
Access-Control-Allow-Origin: http://www.example.com
Access-Control-Allow-Methods: PUT, DELETE

따라서 CORS 에서 Preflight 요청은 OPTIONS 메서드를 사용하기 때문에 웹서버에서 OPTIONS 메서드를 허용하는지 확인이 필요하다.

Credential Request

[작성중]

Non-Credential Request

[작성중]

서버에서 CORS 적용 방법

Apache Web Server

httpd.conf 파일을 다음과 같이 수정한다.

        SetEnvIf Origin "http://(.+\.)?(gurubee.net|oracleclub.com)$" AccessControlAllowOrigin=$0
        Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
        Header set Access-Control-Allow-Credentials "true"
        Header set Access-Control-Allow-Headers "Charset, Content-Type, X-Requested-With, Accept"
        Header set Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE, HEAD"

Spring Framework

아래 설정은 Spring Security 4.1 이상에서 동작하며, Spring Boot은 1.4 이상이다.
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
    }
}
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.csrf().disable();
        http.cors();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH"));
        // setAllowCredentials(true) is important, otherwise:
        // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
        configuration.setAllowCredentials(true);
        // setAllowedHeaders is important! Without it, OPTIONS preflight request
        // will fail with 403 Invalid CORS request
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}


참고자료


댓글

이 블로그의 인기 게시물

macOS가 갑자기 부팅이 되지 않을 경우 데이터 복구 또는 백업 방법

C++로 프로그래밍할 때 인자 또는 리턴 값으로 std::vector 등 STL 데이터 타입 처리하는 좋은 방법

Git 저장소를 병합하는 방법(How to merge repositories in Git)