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) 어디에서 문자열 상수를 넣어 하죠 HEADERSX_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.