Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

임도현의 성장

Spring-Boot Cross-Origin Resource Sharing 본문

Spring Boot

Spring-Boot Cross-Origin Resource Sharing

림도현 2024. 12. 25. 16:18

🥵  CORS란?

도메인이 다른 서버끼리 리소스를 주고 받을 때 브라우저에서는 보안적인 이유로 cross-origin HTTP 요청들을 제한합니다. 그래서 cross-origin 요청을 하려면 서버의 동의가 필요합니다. 만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 동의하지 않는다면 브라우저에서 거절합니다. 이 정책은 악의적인 사이트가 사용자의 데이터를 탈취하지 못하도록, 다른 출처(origin)에서 리소스를 요청할 때 제한을 두는 역할을 합니다.

🎅 CORS 경험 

이 전까지는 하나의 어플리케이션으로 계속 JSP만 하다가 API서버를 만들어 서로 다른 도메인으로 요청하는 작업이 처음이였다. 백앤드 개발자 입장에서는 서버 코드 오류 없이 테스트 까지 했는데 프론트쪽에서 CORS에러가 났다고 해줬다. 그때 당시에는 CORS가 먼데 하고 찾아 보았다.

🧐 출처(Origin) 동일 출처 정책(Same-Origin_Policy) 이란?

  • Protocol : HTTP, HTTPS
  • Host : 사이트 도메인 주소
  • Port : 포트 번호 (생략 가능)
  • Path : 사이트 내부 경로
  • Quert String : 요청의 key 와 ㅍalue값
  • Fragment : 해시 태그

URL에 대한 속성들 중에 Protocol + Host + Port 를 모두 합친 URL을 출처(Origin)라고 한다. 

출처(Origin) 구분 기준은 예를 들어 출처가 https://mildo.xyz/:3000 일 때 밑에 테이블보면 알다시피 Protocol, Host, Port 만 일치하면 된다. 출처가 같으면 리소스를 자유롭게 가져올 수 있게 된다. 이것을 동일 출처 정책(Same-Origin_Policy) SOP라고 부른다.

URL 결과 이유
https://mildo.xyz/:3000/user 같은 출처 Protocol, Host, Port 동일
https://mildo.xyz/:3000/user?query=name 같은 출처 Protocol, Host, Port 동일
https://mildo.xyz/:3030 다른 출처 Port 다름
https://mildo.com/:3030 다른 출처 Host 다름

💩 브라우저의 CORS 기본 동작

프론트에서 백앤드 서버로 요청을 했을 때 CORS에러가 나면 서버쪽 에러라고 착각할 수 있는데 출처를 비교하고 Cross-Origin을 차단하는 일은 브라우저에 구현된 스펙이다. 

브라우저의 CORS기본 동작

  1. 클라이언트에서 HTTP 요청의 헤더에 Origin을 담아서 전달
  2. 서버는 응답 헤더에 Access-Control-Allow-Origin을 담아 전달
  3. 클라이언트의 Origin과 서버의 Access-Control-Allow-Origin을 비교
  4. 유효하지 않다면 CORS에러 발생

🙈 백앤드에서 CORS 설정

Spring Security를 적용하였다면 SecurityConfig에 적용하면 된다.

  • setAllowedOrigins : 어떤 출처로 부터 요청을 허용할지
  • setAllowedHeaders : 서버가 요청에 허용할 HTTP 해더 설정
  • setAllowedMethods : 서버가 요청에 허용할 HTTP 메서드 설정
  • setAllowCredentials : 서버가 쿠키 Authorization 헤더 등을 포함한 요청을 허용하지 여부
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList(
                "https://mildo.xyz",
                "http://localhost:3000"
        ));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"));
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-Requested-With", "Accept"));
        configuration.setAllowCredentials(true);

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

 

🤥 내 생각 정리

CORS는 클라이언트가 요청하는 주소 출처를 확인해서 출처가 같으면 정보들을 자유롭게 가져 갈 수 있게 하고 출처가 다르면 동일 출처 정책 SOP에 의해서 CORS에러를 발생한다. 이때 백엔드 서버에서 검사하는게 아니고 브라우저 안에 구현되어있는 기능이다. CORS에러가 안나게 하기 위해 백엔드 서버에는 출처를 맞춰주는 것이 중요하다. 그리고 나는 JWT 인증 필터도 있었는데 이게 CORS 필터보다 먼저 실행되면 CORS에러가 발생하였다. 왜냐하면 출처 허용은 CORS 필터에 있는데 그것보다 JWT 인증 필터를 먼저 실행했기 때문에 CORS에러가 발생하는거였다.