대머리개발자

크로스 도메인 본문

개발이야기/개념

크로스 도메인

대머리개발자 2022. 12. 30. 10:36
728x90

기본적으로 알고 있는 내용인데 또 고생을 하고 있어서 다시 한번 정리 해본다.

 

늘 시스템 구성(개발환경)은 누군가 미리 해놓고 그 위에 기능적인 개발만 진행하다 보니 당연하게 생각했던 것들이 너무 소중하고 감사했다잉. 그래서들 블러그를 통해서 기록을 하게 되는 것이고 내가 경험했던 시행착오를 통해 누군가의 삽질을 마무의리 할 수 있도록..... But 삽질의 양만큼 실력이 늘어난다고 본다.

 

호랑이 담배 피던 시절에는 하나의 어플리케이션에 프론트와 백엔드가 하나의 서버에 공존 했다..JSP....구구절절....

지금은 모든것이 분업화 되어 프론트(리액트,뷰,...)와 백엔드가 분리되어서 기동이 된다.(어지간하면?)

 

보통 프론트는 nginx(localhost:3000)와 백엔드는 tomcat(localhost:80)등으로 기동한다. 

그럼 두 서버간 도메인이 다르기 때문에 프론트에서 백엔드 호출이 "크로스 도메인이 상황"이 되는 것이다. 

 

문자 그대로 교차되는 도메인

서론이 너무 길었다.... 다른 블로그 가보면 더 서론이 길다. 
뭐 암튼 서로 다른 도메인에서의 호출은 보안적 이슈가 있기에 스펙으로 정의 했고,  해당 스펙(프로토콜)을  "브라우저" 자체에서  구현하여 블로킹하는 것이다. 호출을 막아 버리는 것이다.

 

이 말 자체의 의미를 이제서야 깨달았다. ㅎㄷㄷ 이제라도 알았으니 부지런히 깨달음을 작성해 보자.

 

브라우저 자체에서 막는 것이기 때문에 브라우저를 통하지 않고 직접 서버간 통신하는 API는 크로스 도메인 이슈가 없다는 거... 띠용..

 

그래서 브라우저에서 블로킹 하지 않고 허용해주는 옵션이나 플러그들이 존재한다. 해당 해결책은 내 로컬에서만 사용할 수 있는 일시적인것들이기 때문에 추천박지 않는다.

 

그리고 사실 무조건 적으로 브라우저가 블로킹을 하는 것이 아니고 preflight request를 진행한다.

preflight request : 사전 정찰병(options)을 보내서 내가 진짜 보낼수 있는지 request 하는 역할을 한다.

 

근데  이 또한 무조건 보내는것은 아니다. ㅋㅋㅋ 어렵다 어려워

 

단순 요청은 prefilght 하지 않는다고 한다. 근데 우리는 인증을 헤더에 박아야 하기 때문에 단순 요청을 하지 않는다. 

 

어쨋거나

 

해결책은 나왔다.! 정찰병에게 넌 여기에 request 할 수 있다고 알려 주면 된다!!!!!!

 

프론트에서 해결하는 것이 아닌 근본적으로 서버에서 해결을 해야 한다!!!

 

1. 시큐리티를 사용 할 때

 

   @Override
    protected void configure(HttpSecurity http) throws Exception {{
         http.csrf().//....
             .cors().configurationSource(corsConfigurationSource()                             
    }

   public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOriginPattern("*");
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

 

2. 시큐리티를 사용하지 않을 때 설정

 

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedOrigins("*");
    }
}

 

3. 필터에서 해결

 : 사전 정찰병에게!! 고고싱 보내줌.

 

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
       if(request.getMethod().equals("OPTIONS")) {)) {
            response.setStatus( HttpServletResponse.SC_OK);
            corsDomain( response);
            return;
        }
        ...
     }
     
     protected void corsDomain(HttpServletResponse response){
        response.addHeader("Access-Control-Allow-Credentials", "true");
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Max-Age", "3600");
        response.addHeader("Access-Control-Allow-Methods", "GET, OPTIONS, HEAD, PUT, POST");
        response.addHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization");
    }

자신의 플젝 상황에 따라서 적절하게 구현하면 된다잉

 

## 참고 크로스도메인 스펙 (https://fetch.spec.whatwg.org/#cross-origin-request-with-preflight0)

 

 

## Webflux 에서는!!

 

package com.example.demo;


import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {
        corsRegistry.addMapping("/**")
                .allowedOrigins("*")
//                .allowedMethods("PUT")
                .maxAge(3600);
    }
}

 

## 코틀린 에서는!!

@Configuration
class CorsConfig: WebMvcConfigurer {

    override
    fun addCorsMappings(registry: CorsRegistry) {
        registry.addMapping("/**")
            .allowedOrigins("http://127.0.0.1:3000/")
            .allowedMethods("*")
            .allowedHeaders("authorization", "content-type")
            .allowCredentials(true)
            .maxAge(3600)
    }
}
728x90

'개발이야기 > 개념' 카테고리의 다른 글

개발에선 "절대"는 없다.  (0) 2023.03.14
코딩컨벤션  (0) 2023.03.04
grpc.proto porting  (0) 2023.01.11
역할과 권한 In OAuth2.0  (1) 2023.01.09
What the OAuth2.0  (1) 2023.01.05