Spring Security Fundamentals(3)

Crow·2022년 11월 22일

3.CORS(Crpss-Origin-Resource sharing, 교차 출처 리소스 공유)

  • HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체계
  • 웹 애플리케이션이 리소스가 자신의 출처와 다를 때 브라우저는 요청 헤더에 Origin 필드에 요청 출처를 함께 담아 교차 출처 HTTP 요청을 실행

  • 출처를 비교하는 로직은 서버에 구현된 스펙이 아닌 브라우저에 구현된 스펙 기준으로 처리되며 브라우저는 클라이언트의 요청 헤더와 서버의 응답헤더를 비교해서 최종 응답을 결정

  • 두개의 출처를 비교하는 방법은 URL 구성요소중 Protocol, Host, Post이 세가지가 동일한지 확인하면 되고 나머지는 틀려도 상관없음

  • https://domain-a.com의 프론트 엔드 JavaScript 코드가 XMLHttpRequest(Ajax)를 사용하여 https://domain-b/data.json을 요청하는 경우 보안상의 이유로, 브라우저는 스크립트에서 시작한 쵸차 출처 HTTP 요청을 제한함

  • XMLHttpRequest(Ajax)와 Fetch API는 동일 출처 정책을 따르기 때문에 이 API 사용하는 웹 애플리케이션은 자신의 출처와 동일한 리소스만 불러올 수 있으며, 다른 출처의 리소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 함

CORS 요청의 종류

Simple Request

  • 예비요청(Prefilght)과정 없이 바로 서버에 본 요청을 한 후, 서버가 응답의 헤더에 Access-Control-Allow-Origin과 같은 값을 전송하면 브라우저가 서로 비교후 CORS 정책 위반 여부를 검사하는 방식

  • 제약사항
    1. GET, POST, HEAD 중의 한 가지 Method를 사용해야 한다.

    1. 헤더는 Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width Width만 가능하고 Custom Header는 허용되지 않는다.
    2. Content-type은 application/x-www-form-urlencoded, multipart/form-data. text/plain만 가능하다

PreFlight Request(예비요청)

  • 브라우저는 요청을 한번에 보내지 않고, 예비요청과 본요청으로 나누어 서버에 전달하는데 브라우저가 예비요청을 보내는 것을 Prefilght 라고 하며 이 예비 요청의 메소드에는 OPTIONS가 사용된다

  • 예비요청의 역활은 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 확인하는 것으로 요청 사항이 Simple Request에 해당하지 않을 경우 브라우저가 Prefilght Request 실행


개념 설명 및 API

동일 출처 기준

CORS 해결 - 서버에서 Access-Control-Allow-* 세팅

  • Access-Control-Allow-Origin : 헤더에 작성된 출처만 브라우저가 리소스를 접근할 수 있도록 허용한다

  • Access-Control-Allow-Methods : preflight request에 대한 응답으로 실제 요청중에 사용할 수 있는 메서드를 나타낸다.

    • 기본값은 GET, POST, HEAD, OPTIONS, *
  • Access-Control-Allow-Headers : preflight request에 대한 응갑으로 실제 요청중에 사용할 수 있는 헤더 필드 이름을 나타낸다.

    • 기본값은 Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Custom Header, *
  • Access-Control-Allow-Credentials : 실제 요청에 쿠키나 인증등의 사용자 자격증명이 포함될 수 있음을 나타낸다. Client의 credentials:include일 경우 true 필수

*Access-Control-Allow-Max-Age : preflight 요청 결과를 캐시 할 수 있는 시간을 나타내는 것으로 해당 시간동안은 preflight요청을 다시 하지 않게된다.

CorsConfigurer & CorsFilter

CorsConfigurer

  • Spring Security 필터 체인에 CorsFilter를 추가합니다.

  • corsFilter 라는 이름의 Bean이 제공되면 해당 CorsFilter가 사용된다.

  • corsFilter 라는 이름의 Bean이 없고 CorsConfigurationSource빈이 정의된 경우 해당 CorsConfiguration이 사용된다

  • CorsConfigurationSource 빈이 정의되어 있지 않은 경우 Spring MVC가 클래스 경로에 있으면 HandlerMappingIntrospector가 사용된다.

CorsFilter

  • CORS 예비 요청을 처리하고 CORS 단순 및 본 요청을 가로채고, 제공된 CorsConfigurationSource를 통해 일치된 정책에 따라 CORS 응답 헤더와 같은 응답을 업데이트 하기 위한 필터이다.

  • Spring MVC Java 구성과 Spring MVC XML 네임스페이스에서 CORS를 구성하는 대안이라 볼 수 있다(EX:@CorsOrigin)

  • 스프링 웹에 의존하는 응용프로그램이나 javax.servlet에서 CORS 검사를 수행해야 하는 보안 제약 조건에 유용한 필터이다.

API

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().permitAll();
        http.cors().configurationSource(corsConfigurationSource());

        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {

        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("http://localhost:8080");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);


        return source;
    }

오늘 강의에서 영상으로 코드리뷰를 하면서 느낀것은 나는 지금까지 너무 강직된 개발을 했던거 같다.

나는 항상 project를 개발할때 하나의 프로젝트에 무조건 하나의 모듈이 들어가야 한다고 생각했다.

하지만 이 강의에 코딩 과정을 보면서 무조건 그럴 필요가 없다고 생각했다.


출처

스프링 시큐리티 OAuth2 - Spring Boot 기반으로 개발하는 Spring Security OAuth2(https://www.inflearn.com/course/%EC%A0%95%EC%88%98%EC%9B%90-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0/dashboard)

profile
어제보다 개발 더 잘하기 / 많이 듣고 핵심만 정리해서 말하기 / 도망가지 말기 / 깃허브 위키 내용 가져오기

0개의 댓글