SpringBoot로 개발한 API를 React에서 호출하려면 CORS 설정을 해줘야 한다. (React, SpringBoot 모두 설정해주어야 하는 것으로 알고있다.) 프론트 개발자분이 이거 CORS 오류가 떠요! 하면 어떻게 해결할 수 있는지 알아보자. 🤔
1. CORS란?
교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 웹 보안의 핵심 개념 중 하나로, 다른 출처의 리소스에 대한 접근을 허용하는 메커니즘이다. "출처"는 프로토콜, 도메인(또는 IP 주소), 그리고 포트 번호의 조합으로 정의된다. 예를 들어, https://example.com은 https://another.com 또는 http://example.com:8080 (프로토콜, 도메인, 포트 중 하나라도 다르면)과는 다른 출처로 간주된다.
웹 애플리케이션이 사용자의 브라우저에서 실행될 때, CORS 정책은 해당 애플리케이션이 다른 출처의 리소스를 요청할 수 있는지를 결정한다. 기본적으로, 브라우저는 동일 출처 정책(Same-Origin Policy)을 적용하여, 스크립트가 다른 출처의 리소스를 불러오는 것을 제한한다. 이는 임의의 웹 사이트가 사용자를 대신하여 다른 사이트에 요청을 보내고 그 응답을 읽을 수 없도록 하는 보안 조치이다.
CORS는 이러한 제약을 완화하기 위해 설계되었다. 웹 서버가 추가 HTTP 헤더를 통해 브라우저에 명시적으로 알려줌으로써, 특정 출처에서 온 요청들에 대해 자신의 리소스에 접근할 수 있도록 허용할 수 있다. 이 때, 서버는 Access-Control-Allow-Origin과 같은 CORS 헤더를 응답에 포함시켜, 요청을 보낸 출처가 자신의 리소스에 접근할 수 있도록 허용할 수 있는지를 알려준다.
2. CORS가 필요한 이유
CORS 정책은 웹의 개방성과 보안 사이의 균형을 맞추고자 하는 방식이다. 웹은 본래 상호 연결되고 자원을 공유하는 것이 기본 목표이지만, 이러한 개방성이 사용자의 보안을 위협할 수 있다.
3. SpringBoot에서 CORS 설정 추가하기
먼저, build.gradle 에 security 의존성을 추가한다.
implementation 'org.springframework.boot:spring-boot-starter-security'
다음으로, SecurityConfig 클래스를 작성한다.
- @Configuration: 이 어노테이션은 해당 클래스가 스프링의 설정 파일임을 나타낸다.
- @Bean: 스프링 컨테이너가 관리하는 빈(bean)을 등록한다. 이 메소드가 반환하는 인스턴스인 SecurityFilterChain은 스프링 컨테이너에 의해 관리된다.
- securityFilterChain(HttpSecurity http): 스프링 시큐리티의 HTTP 보안 설정을 커스터마이징한다. 여기서는 .cors().disable()을 통해 스프링 시큐리티의 기본 CORS 설정을 비활성화하고, .csrf().disable()를 통해 CSRF 보호 기능을 비활성화한다. 또한, .formLogin().disable()로 폼 로그인을 비활성화한다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.formLogin(AbstractHttpConfigurer::disable)
.build();
}
}
CorsConfig 클래스를 추가한다.
- @EnableWebSecurity: 이 어노테이션은 스프링 시큐리티 설정을 활성화한다.
- implements WebMvcConfigurer: CorsConfig 클래스는 스프링 MVC를 위한 추가 설정을 제공하는 인터페이스인 WebMvcConfigurer를 구현한다.
- addCorsMappings(CorsRegistry registry): CORS 설정을 커스터마이징한다. 여기서는 모든 경로(/**)에 대해 CORS 요청을 허용하고, 모든 출처(allowedOriginPatterns("*")), 주요 HTTP 메소드(GET, POST, PUT, DELETE), 그리고 크레덴셜(쿠키, HTTP 인증 및 클라이언트 SSL 인증서 등)을 허용한다.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebSecurity
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true);
}
}
여기까지 작성하고 실행을 하면 로그에 Using generated security password, This generated 어쩌구~ 뜨는데, security가 잘 동작하고 있다는 것을 알 수 있다.
나는 위 로그가 보기 싫어서 따로 application.properties 파일에 다음과 같이 스프링 시큐리티의 기본 사용자 이름과 비밀번호를 설정했다.
spring.security.user.name=test
spring.security.user.password=thisIsPw
그러면 security 관련 로그가 뜨지 않는다.
'SpringBoot' 카테고리의 다른 글
RESTful 웹 서비스 구축하기 (0) | 2023.12.30 |
---|---|
스프링 부트는 무엇인가? (0) | 2023.12.29 |