Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS의 개념과 spring에서의 해결법 #8

Open
mr8356 opened this issue Nov 13, 2024 · 0 comments
Open

CORS의 개념과 spring에서의 해결법 #8

mr8356 opened this issue Nov 13, 2024 · 0 comments

Comments

@mr8356
Copy link
Collaborator

mr8356 commented Nov 13, 2024

CORS (Cross-Origin Resource Sharing)

개요

CORS는 웹 애플리케이션이 다른 도메인의 리소스에 접근할 수 있도록 허용하거나 제한하는 메커니즘입니다. 이는 브라우저에서 보안상의 이유로 동일 출처 정책(Same-Origin Policy)을 따르기 때문에 필요합니다.

동작 방식

  1. Preflight 요청: 특정 HTTP 메서드(e.g., PUT, DELETE)나 사용자 정의 헤더를 사용하는 경우, 브라우저는 서버에 사전 요청을 보내 접근 권한을 확인합니다.
  2. 헤더: 서버가 Access-Control-Allow-Origin과 같은 CORS 관련 헤더를 포함해 응답하면 해당 리소스에 대한 접근이 허용됩니다.

주요 CORS 헤더

  • Access-Control-Allow-Origin: 접근을 허용할 도메인 명시 (* 사용 시 모든 도메인 허용)
  • Access-Control-Allow-Methods: 허용할 HTTP 메서드 지정 (e.g., GET, POST)
  • Access-Control-Allow-Headers: 클라이언트에서 사용할 수 있는 헤더 명시

Java Spring에서 CORS 개선 방법

Spring에서는 기본적으로 CORS를 처리할 수 있는 다양한 방법을 제공합니다. 이를 통해 특정 도메인이나 HTTP 메서드에 대한 접근을 제어하거나, 필요한 경우 CORS 정책을 맞춤형으로 설정할 수 있습니다. 아래는 Java Spring에서 CORS를 설정하고 개선할 수 있는 방법들입니다.

1. 전역 CORS 설정 (Global CORS Configuration)

Spring에서는 WebMvcConfigurer 인터페이스를 구현하여 전역적으로 CORS를 설정할 수 있습니다. 이를 통해 애플리케이션의 모든 엔드포인트에 대해 CORS 설정을 통합적으로 관리할 수 있습니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")  // 모든 경로에 대해 CORS 적용
                .allowedOrigins("https://example.com")  // 허용할 도메인
                .allowedMethods("GET", "POST", "PUT", "DELETE")  // 허용할 HTTP 메서드
                .allowedHeaders("Authorization", "Content-Type")  // 허용할 요청 헤더
                .allowCredentials(true)  // 자격 증명(쿠키, 인증 정보) 허용
                .maxAge(3600);  // preflight 요청 캐시 시간 (초 단위)
    }
}

2. 컨트롤러 단위 CORS 설정 (Controller-specific CORS)

특정 컨트롤러나 메서드에 대해 CORS 설정을 하고 싶다면 @CrossOrigin 어노테이션을 사용할 수 있습니다. 이를 통해 더 세밀한 제어가 가능합니다.

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExampleController {

    @CrossOrigin(origins = "https://example.com", methods = { RequestMethod.GET, RequestMethod.POST })
    @GetMapping("/example")
    public String getExample() {
        return "Hello, CORS!";
    }
}

3. CORS 필터를 통한 커스터마이징

보다 복잡한 CORS 정책을 설정하려면 Filter를 사용하여 커스터마이징할 수 있습니다. 이 방식은 요청/응답 헤더를 직접 제어하거나, 조건에 따라 CORS 정책을 동적으로 변경할 수 있습니다.

import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        response.setHeader("Access-Control-Allow-Origin", "https://example.com");  // 허용 도메인
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        // Preflight 요청 처리 (OPTIONS 메서드)
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        }
        
        filterChain.doFilter(request, response);  // 나머지 필터 체인 계속 처리
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 필터 초기화 로직
    }

    @Override
    public void destroy() {
        // 필터 종료 로직
    }
}

4. Spring Security와 CORS 통합

Spring Security를 사용하는 경우 CORS 설정이 보안 필터 체인에 의해 막힐 수 있습니다. 이럴 때는 Spring Security 설정에서 CORS를 명시적으로 허용해야 합니다.

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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors()  // CORS 설정 활성화
            .and()
            .authorizeRequests()
            .antMatchers("/**").permitAll();  // 모든 요청에 대해 허용
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);  // 모든 경로에 CORS 설정 적용
        return source;
    }
}

5. CORS 정책 개선 팁

  • 특정 경로에만 CORS 적용: 보안을 강화하기 위해 모든 엔드포인트에 CORS를 허용하는 대신 필요한 경로만 설정하세요.
  • 허용할 메서드와 헤더 제한: 허용할 메서드(GET, POST 등)와 헤더(Authorization, Content-Type 등)를 명확히 지정하여 불필요한 접근을 차단하세요.
  • allowCredentials 사용 시 주의: allowCredentials(true)를 사용할 때는 Access-Control-Allow-Origin 헤더에 *을 사용할 수 없습니다. 이는 보안상의 이유로 허용되지 않습니다.
  • Preflight 캐시 설정: Preflight 요청의 캐시 시간(maxAge)을 적절히 설정하여 불필요한 요청을 줄일 수 있습니다.

Spring에서는 CORS 정책을 이렇게 설정함으로써 다른 도메인 간의 리소스 공유를 안전하게 관리할 수 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant