spring-boot 및 angularjs가 작동하지 않는 CORS


87

한 애플리케이션 (스프링 부트 애플리케이션)에서 다른 애플리케이션 (angularjs)에서 REST 엔드 포인트를 호출하려고합니다. 애플리케이션은 다음 호스트 및 포트에서 실행 중입니다.

  • REST 애플리케이션, 스프링 부트 사용, http://localhost:8080
  • angularjs를 사용하는 HTML 애플리케이션, http://localhost:50029

나는 또한 spring-security봄 부팅 응용 프로그램과 함께 사용 하고 있습니다. HTML 애플리케이션에서 REST 애플리케이션에 대해 인증 할 수 있지만 이후에도 여전히 REST 엔드 포인트에 액세스 할 수 없습니다. 예를 들어, 다음과 같이 정의 된 angularjs 서비스가 있습니다.

adminServices.factory('AdminService', ['$resource', '$http', 'conf', function($resource, $http, conf) {
    var s = {};
    s.isAdminLoggedIn = function(data) {
        return $http({
            method: 'GET',
            url: 'http://localhost:8080/api/admin/isloggedin',
            withCredentials: true,
            headers: {
                'X-Requested-With': 'XMLHttpRequest'
            }
        });
    };
    s.login = function(username, password) {
        var u = 'username=' + encodeURI(username);
        var p = 'password=' + encodeURI(password);
        var r = 'remember_me=1';
        var data = u + '&' + p + '&' + r;

        return $http({
            method: 'POST',
            url: 'http://localhost:8080/login',
            data: data,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        });
    };
    return s;
}]);

angularjs 컨트롤러는 다음과 같습니다.

adminControllers.controller('LoginController', ['$scope', '$http', 'AdminService', function($scope, $http, AdminService) {
    $scope.username = '';
    $scope.password = '';

    $scope.signIn = function() {
        AdminService.login($scope.username, $scope.password)
            .success(function(d,s) {
                if(d['success']) {
                    console.log('ok authenticated, call another REST endpoint');
                    AdminService.isAdminLoggedIn()
                        .success(function(d,s) {
                            console.log('i can access a protected REST endpoint after logging in');
                        })
                        .error(function(d, s) { 
                            console.log('huh, error checking to see if admin is logged in');
                            $scope.reset();
                        });
                } else {
                    console.log('bad credentials?');
                }
            })
            .error(function(d, s) {
                console.log('huh, error happened!');
            });
    };
}]);

호출에하는 http://localhost:8080/api/admin/isloggedin, 내가 얻을 401 Unauthorized.

REST 애플리케이션 측에는 다음과 같은 CORS 필터가 있습니다.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {

    @Override
    public void destroy() { }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:50029");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, X-Auth-Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        if(!"OPTIONS".equalsIgnoreCase(request.getMethod())) {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig config) throws ServletException { }
}

내 봄 보안 구성은 다음과 같습니다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    private JsonAuthSuccessHandler jsonAuthSuccessHandler;

    @Autowired
    private JsonAuthFailureHandler jsonAuthFailureHandler;

    @Autowired
    private JsonLogoutSuccessHandler jsonLogoutSuccessHandler;

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Value("${rememberme.key}")
    private String rememberMeKey;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .exceptionHandling()
            .authenticationEntryPoint(restAuthenticationEntryPoint)
                .and()
            .authorizeRequests()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/", "/admin", "/css/**", "/js/**", "/fonts/**", "/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .successHandler(jsonAuthSuccessHandler)
                .failureHandler(jsonAuthFailureHandler)
                .permitAll()
                .and()
            .logout()
                .deleteCookies("remember-me", "JSESSIONID")
                .logoutSuccessHandler(jsonLogoutSuccessHandler)
                .permitAll()
                .and()
            .rememberMe()
                .userDetailsService(userDetailsService)
                .tokenRepository(persistentTokenRepository)
                .rememberMeCookieName("REMEMBER_ME")
                .rememberMeParameter("remember_me")
                .tokenValiditySeconds(1209600)
                .useSecureCookie(false)
                .key(rememberMeKey);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .authenticationProvider(authenticationProvider);
    }
}

모든 핸들러는 {success: true}사용자가 로그인했는지, 인증에 실패했는지, 로그 아웃했는지에 따라 JSON 응답을 작성 합니다. RestAuthenticationEntryPoint외모는 다음을 좋아한다.

@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException ex)
            throws IOException, ServletException {
        resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }

}

내가 무엇을 놓치고 있거나 잘못하고 있는지에 대한 아이디어가 있습니까?


토큰이나 다른 것과 같은 인증도 수행해야한다고 생각합니다. 2 개의 서버가 있습니다. 그 튜토리얼을 보셨습니까? spring.io/guides/tutorials/spring-security-and-angular-js
— Gokhan Oner

@GokhanOner 인증은 어떻게 수행합니까? 그것은 아마도이 문제에서 빠진 부분 일 것입니다. 또한 예, 나는 그 튜토리얼을 살펴 보았고 그것이 내 접근 방식과 일치한다고 생각하지 않았습니다. 처음 두 부분은 Http-Basic 인증을 다루고, 세 번째 부분은 Redis를 다루고 (종속성으로 얻고 싶지 않았거나 계획하지 않았 음), 마지막 튜토리얼은 API Gateway스프링 클라우드에 관한 것이 었는데, 이는 과잉이라고 생각했습니다. .
— Jane Wayne

redis 없이도 할 수 있다고 가정합니다. 키-값 캐시 저장소 일뿐입니다. 인증 및 CSRF 토큰을 매장에 저장해야하며, 맵 내부에서 즉시 가능합니다. 여기서 핵심은 인증 키입니다. 예제를보십시오 : github.com/dsyer/spring-security-angular/tree/master/… 그리고 "자원 서버"가있는 페이지. 몇 가지 추가 빈이 정의되어 있으며 CORS 필터의 순서도 중요합니다. 그리고 약간의 소품. 변경도 필요합니다.
— Gokhan Oner

좋아, 나는 빠른 조사를했다. Redis를 제거하기 위해 필요한 것은 springSessionRepositoryFilter 빈을 크레이트하고 github.com/spring-projects/spring-session/blob/1.0.0.RC1/… 및 sessionRepository 빈과이 빈을 보는 것입니다. RedisOperationsSessionRepository 대신 Spring 세션에있는 MapSessionRepository를 사용할 수 있습니다. 그런 다음 예를 따르십시오.
— Gokhan Oner 2015-08-31

답변:


102
import java.io.IOException;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

public SimpleCORSFilter() {
    log.info("SimpleCORSFilter init");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}

이 필터를 추가로 정의 할 필요가 없습니다.이 클래스를 추가하기 만하면됩니다. 봄이 스캔되어 추가됩니다. SimpleCORSFilter. 예 : spring-enable-cors


몇 가지 질문입니다. 1) 어디에서 문자열 상수를 넣어 하죠 HEADERS와 X_REDIRECT_LOCATION_HEADER? 2) 줄 request.getRequestURL());이 오타이거나 복사 / 붙여 넣기 오류입니까? 3) 왜 OPTIONS필터 체인을 확인하지 않고 계속 진행합니까?
— Jane Wayne

2
그러나 AuthenticationEntryPoint 실행을 차단합니다 .. 가이드를 부탁드립니다
— Pra_A

1
감사합니다. 봄과 불씨가 함께 일하기 위해 노력하는 데 큰 도움이되었습니다. 힘내 친구 야!
— Tomasz Szymanek

FindBugs는 다음을 사용하여 헤더 매개 변수를 설정하는 것을 좋아하지 않습니다 : HTTP 응답 분할로request.getHeader("Origin") 인해 위와 같이
— Glenn

3
응용 프로그램에 다른 필터가있는 경우이 필터는 필터에 주석을 추가하여 우선 순위가 가장 높아야합니다 @Order(Ordered.HIGHEST_PRECEDENCE) .
— Shafiul

43

나는 비슷한 상황에 처해 있었다. 연구와 테스트를 마친 후 발견 한 내용은 다음과 같습니다.

  1. Spring Boot에서 전역 CORS를 활성화하는 권장 방법은 Spring MVC 내에서 선언하고 다음과 @CrossOrigin같이 세분화 된 구성 과 결합하는 것입니다.

    @Configuration
    public class CorsConfig {
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                            .allowedHeaders("*");
                }
            };
        }
    }
    
  2. 이제 Spring Security를 ​​사용하고 있기 때문에 Spring Security 수준에서 CORS를 활성화해야하며 Spring MVC 수준에서 정의 된 구성을 다음과 같이 활용할 수 있도록해야합니다.

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and()...
        }
    }
    

    다음 은 Spring MVC 프레임 워크에서 CORS 지원을 설명하는 매우 훌륭한 튜토리얼입니다.


3
ups는이 변경 사항과 함께 작동합니다. http .csrf () .disable () .cors () .and ()
— marti_

1
@Osgux :) 내가 JWT를 사용하고 있고 csrf가 안전하기 때문에 나는 거기에 넣지 않았다 .. 그것이 도움이된다면 upvote하는 것을 잊지 마세요 :)
— Yogen Rai

그래 나는 +1 = D를 추가했다
— marti_ 2017

@Marcel 어떤 문제가 발생합니까?
— Yogen Rai

<my rest address>로드 실패 : 프리 플라이트 요청에 대한 응답이 액세스 제어 검사를 통과하지 못했습니다. 요청 된 리소스에 'Access-Control-Allow-Origin'헤더가 없습니다. 따라서 원본 ' localhost : 8090 '은 액세스가 허용되지 않습니다.
— Marcel

22

필터를 사용하지 않거나 구성 파일없이 CORS를 활성화하려면 다음을 추가하십시오.

@CrossOrigin

컨트롤러의 맨 위로 이동하면 작동합니다.


4
이 접근 방식을 따를 경우 보안 위험은 무엇입니까?
— Balaji Vignesh

나를 위해 일했고 응답에 헤더를 직접 추가하려고 시도했지만 프리 플라이트가 처리되지 않았기 때문에 작동하지 않았습니다. 나는 이것이 안전하지 않다고 생각하지만 일부 내부 앱이 사용될 수 있습니다.
— amisiuryk

나를 위해 일했습니다. 내부 애플리케이션을위한 매우 편리한 솔루션입니다.
— 아제 쿠마

8

위의 다른 답변을 기반으로 빌드하려면 Spring 보안이 포함 된 Spring 부트 REST 서비스 애플리케이션 (Spring MVC 아님)이있는 경우 Spring 보안을 통해 CORS를 활성화하는 것으로 충분합니다 (Spring MVC를 사용하는 경우 WebMvcConfigurerYogen에서 언급 한대로 Bean 을 사용하면 Spring 보안으로가는 길은 거기에 언급 된 CORS 정의에 위임됩니다)

따라서 다음을 수행하는 보안 구성이 필요합니다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    //other http security config
    http.cors().configurationSource(corsConfigurationSource());
}

//This can be customized as required
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    List<String> allowOrigins = Arrays.asList("*");
    configuration.setAllowedOrigins(allowOrigins);
    configuration.setAllowedMethods(singletonList("*"));
    configuration.setAllowedHeaders(singletonList("*"));
    //in case authentication is enabled this flag MUST be set, otherwise CORS requests will fail
    configuration.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

}

이 링크에는 동일한 정보가 더 있습니다. https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors

노트 :

  1. prod 배포 응용 프로그램에 대해 모든 출처 (*)에 대해 CORS를 활성화하는 것이 항상 좋은 생각은 아닙니다.
  2. CSRF는 문제없이 Spring HttpSecurity 사용자 정의를 통해 활성화 될 수 있습니다.
  3. Spring을 사용하여 앱에서 인증을 활성화 한 경우 ( UserDetailsService예 : a 를 통해 ) 다음을 configuration.setAllowCredentials(true);추가해야합니다.

Spring boot 2.0.0.RELEASE (즉, Spring 5.0.4.RELEASE 및 Spring security 5.0.3.RELEASE)에 대해 테스트되었습니다.


이것은 내 문제를 해결했습니다. Spring과 Spring Boot를 처음 접했기 때문에 Sring MVC로 빌드하지 않았 음을 깨달았습니다. Vue.js 클라이언트가 있습니다. 다른 답변은 Spring MVC에 대한 것처럼 보였지만이 답변은 이미 구현 된 인증 및 권한 부여와 잘 연결되었습니다.
— jaletechs

안녕하세요 @jaletechs, 저도 nuxtJs (vuejs 프레임 워크)를 사용하고 있지만 쿠키 설정에 관해서는 작동하지 않습니다. 이것에 대해 친절하게 도와 주시겠습니까?
— KAmit 19

6

임 사용 spring boot 2.1.0나는 하고 나를 위해 일한 것은

A. 다음을 통해 cors 매핑을 추가합니다.

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

B. HttpSecurity봄 보안을 위해 아래 구성을 my 에 추가하십시오.

.cors().configurationSource(new CorsConfigurationSource() {

    @Override
    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.setAllowedMethods(Collections.singletonList("*"));
        config.addAllowedOrigin("*");
        config.setAllowCredentials(true);
        return config;
    }
})

또한 Zuul 프록시의 경우이 INSTEAD OF A 및 BHttpSecurity.cors() 를 사용할 수 있습니다 (스프링 보안에서 활성화 하기 위해 사용).

@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("HEAD");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

return new CorsFilter (소스); 그런 생성자 오류가 아닙니다
— Aadam

@Aadam 저와 같은 버전의 스프링 부트를 사용하고 있습니까?
— 9 월 GH

2.1.5 사용
— Aadam 2010 년

@Aadam 불행히도 그 이유가 될 수 있습니다.
— 9 월 GH

@Aadam에서 CorsFilter를 사용하고 있는지 확인하십시오 org.springframework.web.filter.CorsFilter. 실수로 catalina 패키지에서 사용하는 동안 동일한 문제가 발생했습니다.
— 9 월 GH

5

이것은 나를 위해 작동합니다.

@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter  {
   //...
   @Override
   protected void configure(HttpSecurity http) throws Exception {

       //...         

       http.cors().configurationSource(new CorsConfigurationSource() {

        @Override
        public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowedHeaders(Collections.singletonList("*"));
            config.setAllowedMethods(Collections.singletonList("*"));
            config.addAllowedOrigin("*");
            config.setAllowCredentials(true);
            return config;
        }
      });

      //...

   }

   //...

}

이 코드가 질문에 답할 수 있지만,이 코드가 질문에 답하는 이유 및 / 또는 방법에 대한 추가 컨텍스트를 제공하면 장기적인 가치가 향상됩니다.
— Adriano Martins

1
Spring 보안을 통해 인증이 활성화 된 경우 config.setAllowCredentials (true); 그렇지 않으면 CORS 요청이 계속 실패합니다
— Deepak

2

저에게 스프링 보안이 사용될 때 100 % 효과가 있었던 유일한 것은 여분의 필터와 빈의 모든 추가 보풀과 간접적 인 "마법"사람들이 그들에게 효과가 있지만 저에게는 그렇지 않다고 제안하는 모든 것을 건너 뛰는 것입니다.

대신 일반으로 필요한 헤더를 작성하도록 강제하십시오 StaticHeadersWriter.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

        http
            // your security config here
            .authorizeRequests()
            .antMatchers(HttpMethod.TRACE, "/**").denyAll()
            .antMatchers("/admin/**").authenticated()
            .anyRequest().permitAll()
            .and().httpBasic()
            .and().headers().frameOptions().disable()
            .and().csrf().disable()
            .headers()
            // the headers you want here. This solved all my CORS problems! 
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", "*"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Methods", "POST, GET"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Max-Age", "3600"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Credentials", "true"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization"));
    }
}

이것이 제가 발견 한 가장 직접적이고 명시적인 방법입니다. 누군가에게 도움이되기를 바랍니다.


1

1 단계

컨트롤러에 @CrossOrigin주석을 달면 CORS 구성이 허용됩니다.

@CrossOrigin
@RestController
public class SampleController { 
  .....
}

2 단계

Spring에는 이미 CorsFilter가 있지만 다음과 같이 자신의 구성을 제공하기 위해 자신의 CorsFilter를 bean으로 등록 할 수 있습니다.

@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(Collections.singletonList("http://localhost:3000")); // Provide list of origins if you want multiple origins
    config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
    config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH"));
    config.setAllowCredentials(true);
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

0

이것을 확인하십시오 :

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    ...
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
    ...
}

이 코드가 질문에 답할 수 있지만,이 코드가 질문에 답하는 이유 및 / 또는 방법에 대한 추가 컨텍스트를 제공하면 장기적인 가치가 향상됩니다.
— rollstuhlfahrer

0

WebSecurityConfigurerAdapter 클래스를 확장하고 @EnableWebSecurity 클래스에서 configure () 메서드를 재정의하면 작동합니다. 아래는 샘플 클래스입니다.

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

         http
        .csrf().disable()
        .exceptionHandling();
         http.headers().cacheControl();

        @Override
        public CorsConfiguration getCorsConfiguration(final HttpServletRequest request) {
            return new CorsConfiguration().applyPermitDefaultValues();
        }
    });
   }
}

0

원래 프로그램이 스프링 보안을 사용하지 않고 코드 변경을 감당할 수 없다면 간단한 리버스 프록시를 생성하면 트릭을 수행 할 수 있습니다. 제 경우에는 다음 구성으로 Nginx를 사용했습니다.

http {
  server {
    listen 9090;
    location / {
      if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      #
      # Custom headers and headers various browsers *should* be OK with but aren't
      #
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      #
      # Tell client that this pre-flight info is valid for 20 days
      #
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Content-Type' 'text/plain; charset=utf-8';
      add_header 'Content-Length' 0;
      return 204;
      }
      if ($request_method = 'POST') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
      }
      if ($request_method = 'GET') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
      }

      proxy_pass http://localhost:8080;
    }
  }
}

내 프로그램은 다음을 수신합니다 : 8080 .

참고 : Nginx의 CORS


0

이것이 나를 위해 일한 것입니다.

@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

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

        http.cors();
    }

}

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
            .addMapping("/**")
            .allowedMethods("*")
            .allowedHeaders("*")
            .allowedOrigins("*")
            .allowCredentials(true);
    }

}

0

이 대답은 @abosancic 대답을 복사하지만 CORS 공격 을 피하기 위해 추가 안전을 추가합니다 .

팁 1 : 액세스가 허용 된 호스트 목록을 확인하지 않고 들어오는 Origin을 그대로 반영하지 마십시오.

팁 2 : 화이트리스트에있는 호스트에 대해서만 자격 증명 요청을 허용합니다.

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

    private List<String> allowedOrigins;

    public SimpleCORSFilter() {
        log.info("SimpleCORSFilter init");
        allowedOrigins = new ArrayList<>();
        allowedOrigins.add("https://mysafeorigin.com");
        allowedOrigins.add("https://itrustthissite.com");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String allowedOrigin = getOriginToAllow(request.getHeader("Origin"));

        if(allowedOrigin != null) {
            response.setHeader("Access-Control-Allow-Origin", allowedOrigin);
            response.setHeader("Access-Control-Allow-Credentials", "true");
        }

        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

    public String getOriginToAllow(String incomingOrigin) {
        if(allowedOrigins.contains(incomingOrigin.toLowerCase())) {
            return incomingOrigin;
        } else {
            return null;
        }
    }
}

0

Spring Boot 앱에서 다음과 같이 CorsConfigurationSource를 설정했습니다.

allowedOrigns먼저 추가 하고 설정 하는 순서로 applyPermitDefaultValues()Spring이 허용 된 헤더, 노출 된 헤더, 허용 된 메소드 등에 대한 기본값 을 설정 하도록하여이를 지정할 필요가 없습니다.

    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:8084"));
        configuration.applyPermitDefaultValues();

        UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
        configurationSource.registerCorsConfiguration("/**", configuration);
        return configurationSource;
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/api/**")
                .access("@authProvider.validateApiKey(request)")
                .anyRequest().authenticated()
                .and().cors()
                .and().csrf().disable()
                .httpBasic().authenticationEntryPoint(authenticationEntryPoint);

        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

0

다음 과 같이 단일 클래스를 만드십시오. 모든 것이 잘 될 것입니다.

        @Component
        @Order(Ordered.HIGHEST_PRECEDENCE)
        public class MyCorsConfig implements Filter {

            @Override
            public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
                final HttpServletResponse response = (HttpServletResponse) res;
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
                response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, enctype");
                response.setHeader("Access-Control-Max-Age", "3600");
                if (HttpMethod.OPTIONS.name().equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
                    response.setStatus(HttpServletResponse.SC_OK);
                } else {
                    chain.doFilter(req, res);
                }
            }

            @Override
            public void destroy() {
            }

            @Override
            public void init(FilterConfig config) throws ServletException {
            }
        }

0

이것은 Spring 부트와 React 사이에 CORS를 비활성화하기 위해 나를 위해 일한 것입니다.

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    /**
     * Overriding the CORS configuration to exposed required header for ussd to work
     *
     * @param registry CorsRegistry
     */

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(4800);
    }
}

보안 구성도 아래와 같이 수정해야했습니다.

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .cors().configurationSource(new CorsConfigurationSource() {

                @Override
                public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                    CorsConfiguration config = new CorsConfiguration();
                    config.setAllowedHeaders(Collections.singletonList("*"));
                    config.setAllowedMethods(Collections.singletonList("*"));
                    config.addAllowedOrigin("*");
                    config.setAllowCredentials(true);
                    return config;
                }
            }).and()
                    .antMatcher("/api/**")
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and().httpBasic()
                    .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and().exceptionHandling().accessDeniedHandler(apiAccessDeniedHandler());
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.