복붙노트

[SPRING] 스프링 부트의 CORS 정책 충돌

SPRING

스프링 부트의 CORS 정책 충돌

저는 스프링 부트를 처음 사용하고 스프링 부트를 사용하여 몇 가지 기본 REST API를 구현했습니다. 그리고 반응을 사용하여 해당 API를 호출하려고하면 일부 CORS 정책을 호출하는 중 오류가 발생했습니다. 그런 다음 그 문제에 대한 해결책을 찾았습니다. 그리고 모든 api 끝점은 로그인 API 호출을 제외하고 올바르게 작동합니다. 그것은 같은 오류를 호출,

여기 내 웹 보안 자바 클래스입니다.

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    private final UserService userDetailsService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    public WebSecurity(UserService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.userDetailsService = userDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL)
                .permitAll().anyRequest().authenticated().and().cors().and().addFilter(getAuthenticationFilter())
                .addFilter(new AuthorizationFilter(authenticationManager())).sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }

    public AuthenticationFilter getAuthenticationFilter() throws Exception {
        final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager());
        filter.setFilterProcessesUrl("/users/login");
        return filter;
    }
}

그리고 여기 예제 코드 예제가 있습니다.

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    UserService userService;

    @CrossOrigin
    @GetMapping(path = "/{id}", 
            produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
    public UserRest getUser(@PathVariable String id) {

        UserRest returnValue = new UserRest();

        UserDto userDto = userService.getUserByUserId(id);
        BeanUtils.copyProperties(userDto, returnValue);

        return returnValue;
    }

    @CrossOrigin
    @PostMapping(
            consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE }, 
            produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
    public UserRest createUser(@RequestBody UserDetailsRequestModel userDetails) {

        UserRest returnValue = new UserRest();

        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(userDetails, userDto);

        UserDto createUser = userService.createUser(userDto);
        BeanUtils.copyProperties(createUser, returnValue);

        return returnValue;
    }
}

나는이 문제에 붙어있어 정말 도움이 필요하다. 내 질문에 simillar로 stackoverflow 주어진 몇 가지 답변을 시도했다. 하지만 그건 내 문제를 해결하지 못했습니다. Mt Spring 부트 버전은 2.1.4입니다.

해결법

  1. ==============================

    1.포트 8080에서 백 엔드에 cors를 허용했지만 로컬에서 포트 3000에서 반응을 보였으므로 문제가 발생했습니다. 따라서 springboot는 다른 포트 주소에서 오는 요청을 받아들이지 않습니다.

    포트 8080에서 백 엔드에 cors를 허용했지만 로컬에서 포트 3000에서 반응을 보였으므로 문제가 발생했습니다. 따라서 springboot는 다른 포트 주소에서 오는 요청을 받아들이지 않습니다.

    방법 1 :

    다음과 같은 주석을 사용하여이 문제를 해결할 수 있습니다.

    @CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)
    

    springboot를 사용하고 있으므로, 다음의 글로벌 설정을 사용하여 모든 도메인이 백엔드에 액세스 할 수 있도록 정의 할 수 있습니다.

    @Configuration
    public class MyConfiguration {
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://localhost:3000")
                        .allowedMethods("PUT", "DELETE", "GET", "POST") //or allow all as you like
                        .allowedHeaders("header1", "header2", "header3")
                        .exposedHeaders("header1", "header2")
                        .allowCredentials(false).maxAge(3600);
                 }
            };
        }
    }
    

    여전히 문제가있는 경우 스프링 보안이 응답 헤더에 Access-Control-Allow-Origin과 같은 CORS 헤더를 추가하지 않기 때문일 수 있습니다. 이 경우 사용자 지정 CORS 필터를 정의하고이를 봄 보안에 추가하여 모든 봄 보안 끝점에 CORS 응답 헤더가 설정되도록 할 수 있습니다. 다음과 같이 필터 빈을 생성 할 수 있습니다.

    public class CorsFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            HttpServletRequest request= (HttpServletRequest) servletRequest;
    
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
            response.setHeader("Access-Control-Allow-Headers", "*");
            response.setHeader("Access-Control-Allow-Credentials", true);
            response.setHeader("Access-Control-Max-Age", 180);
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    

    방법 2 :

    스프링 보안을 사용하고 있기 때문에 다음과 같은 스프링 보안과 함께 CORS 구성을 추가 할 수 있습니다.

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and()
                //other configurations that you want
        }
    
        @Bean
        CorsConfigurationSource corsConfigurationSource()
        {
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(Arrays.asList("*"));
            //or any domain that you want to restrict to 
            configuration.setAllowedMethods(Arrays.asList("GET","POST"));
            //Add the method support as you like
            UrlBasedCorsConfigurationSource source = new     UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration);
            return source;
        }
    } 
    

    Spring 보안은 여러분이 나의 지식에 따라 메소드 1 에서처럼 그것을 제공하더라도 CORS 설정을 사용합니다. 그러나 스프링 문서에서는 CORS에 스프링 보안을 등록하는 방법을 제공했습니다.

    당신이 첨부 한 콘솔 로그에 반환 된 HTTP 상태가 정상이 아니기 때문에 사전 비행 확인이 실패했다고합니다. 그래서 방법 2와 같은 cors를 등록하고 필터가 추가되어 헤더가 응답에 올바르게 추가 될 수 있습니까? . Springboot는 로그인 페이지에 액세스 할 때 사전 비행 확인을 차단합니다. 스프링 보안으로 cors 설정을 제대로해야만 다른 페이지에서 로그인 페이지에 액세스 할 수 있습니다.

    로그인 페이지 / 로그인 매핑에 CORS 허용이 있는지 확인하십시오.

    공식 문서 참조 문서

  2. ==============================

    2.이 시도,

    이 시도,

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

    너는 또한 아래에 할 수 있었다,

    @Bean
    public FilterRegistrationBean corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowCredentials(true);
            config.setAllowedOrigins(Collections.singletonList("*"));
            config.addAllowedHeader("*");
            config.addAllowedMethod("*");
            source.registerCorsConfiguration("/**", config);
            FilterRegistrationBean<CorsFilter> filterRegistration = new FilterRegistrationBean<>(new CorsFilter(source));
            filterRegistration.setOrder(Ordered.HIGHEST_PRECEDENCE);
            return filterRegistration;
    }
    
  3. from https://stackoverflow.com/questions/56759527/cors-policy-conflict-in-spring-boot by cc-by-sa and MIT license