2016-11-03 3 views
0

У меня есть служба REST службы Spring Boot/Spring, позволяющая получить доступ к ряду ресурсов. Некоторые из этих ресурсов (например, /detections) свободно доступны, другие (например, /users) требуют базового HTTP-аутентификации. При тестировании службы REST с CURL все работает так, как ожидалось. Проблемы возникают, когда я пытаюсь получить доступ к сервису из веб-приложения Angular2.Запрос предварительной проверки CORS в Spring Data REST

В этом случае у меня нет никаких проблем при доступе к незащищенным ресурсам http://api.mydomain.com/detections:

this.http.get(this.DETECTIONS_API_ENDPOINT).subscribe(
          response => { 
           ... 
          }, 
          error => { 
           ... 
          } 
        ); 

Но если я пытаюсь получить доступ к защищенному ресурсу http://api.mydomain.com/users, передавая необходимые заголовки с правильным именем пользователя и паролем:

let headers = new Headers(); 
    headers.append('Content-Type', 'application/json'); 
    headers.append('Authorization', 'Basic ' + btoa(username+':'+password)); 

    return this.http.get(this.USERS_API_ENDPOINT, { body: "", headers: headers }).subscribe(
          response => { 
           ... 
          }, 
          error => { 
           ... 
          } 
        ); 

Я получаю (в консоли Firefox) ошибку, которая говорит cross-origin request blocked... Reason: CORS preflight request unsuccessfull (обратите внимание, что это мой перевод с итальянского языка. Я не смог найти точное соответствующее сообщение об ошибке на английском языке. Разница между двумя вызовами, по-видимому, заключается в прохождении заголовков во втором случае, что вызывает отправку OPTIONS вместо запроса GET.

Это моя конфигурация пружины безопасности:

@Configuration 
public class MyAppConfigurationSecurity extends WebSecurityConfigurerAdapter { 

    private Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder(); 

    @Autowired 
    private UserDetailsService myAppUserService; 

    /** 
    * HttpSecurity URL configuration settings. Configure authentication necessary for POST but not for GET 
    */ 

    @Override 
    protected void configure(HttpSecurity http) throws Exception 
    { 
     http.csrf().disable() 
      .authorizeRequests() 
       .antMatchers(HttpMethod.GET, "/detections").permitAll() 
       .antMatchers(HttpMethod.GET, "/detections/search/findTop5ByOrderByTimestampDesc").permitAll() 
       .antMatchers("/users").hasAuthority("ADMIN") 
       .antMatchers("/roles").hasAuthority("ADMIN") 
       .antMatchers("**").authenticated() 
      .and().httpBasic().and() 
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 
    } 


    /** 
    * Sets custom MyAppUserService bean as user detail service 
    */ 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(myAppUserService).passwordEncoder(md5PasswordEncoder); 
    } 

} 

Это конфигурация CORS фильтра; Я добавил этот класс по предложению в Spring Data Rest and Cors, и сначала он решил проблему доступа к CORS для доступа к незащищенным ресурсам. К сожалению, это не похоже на работу в случае защищаемого ресурса:

@Configuration 
public class MyAppConfigurationCors { 

    @Bean 
    public CorsFilter corsFilter() { 

     UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
     CorsConfiguration config = new CorsConfiguration(); 
     config.setAllowCredentials(true); // you USUALLY want this 
     config.addAllowedOrigin("*"); 
     config.addAllowedHeader("*"); 
     config.addAllowedMethod("GET"); 
     config.addAllowedMethod("OPTIONS"); // I added this in a second phase, but nothing changes 
     source.registerCorsConfiguration("/**", config); 
     return new CorsFilter(source); 
    } 
} 
+0

проверить эту ссылку http://stackoverflow.com/a/40374505/4793153 – Eswar

+0

Мне не очень понятно, как это должно работать: я попытался заменить свой класс конфигурации MyAppConfigurationCors'ом компонентом Filter, как в тексте вопроса , затем попытался поместить тест 'if (" OPTIONS "...' в метод 'doFilter', но я не уверен, что делаю все правильно. В любом случае у меня все еще есть ошибка ... – chrx

ответ

2

Пожалуйста, обратитесь к документации Spring о том, как интегрировать CORS and Spring Security.

CORS должны быть обработаны первым:

@EnableWebSecurity 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      // by default uses a Bean by the name of corsConfigurationSource 
      .cors().and() 
      ... 
    } 

    @Bean 
    CorsConfigurationSource corsConfigurationSource() { 
     CorsConfiguration configuration = new CorsConfiguration(); 
     configuration.setAllowedOrigins(Arrays.asList("https://example.com")); 
     configuration.setAllowedMethods(Arrays.asList("GET","POST")); 
     UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
     source.registerCorsConfiguration("/**", configuration); 
     return source; 
    } 
} 
1

Вы можете добавить фильтр в Cors перед первым Spring Security Filter т.е. ChannelProcessingFilter. Следующий фрагмент кода поможет объяснить больше.

protected void configure(HttpSecurity http) throws Exception { 
http.requiresChannel().antMatchers("/*").requires(ANY_CHANNEL).and() 
.authorizeRequests().antMatchers("/api/customer/**").permitAll() 
.antMatchers("/api/signin").permitAll() 
.antMatchers("/api/**").permitAll() 
.antMatchers("/**").permitAll().and() 
.addFilterBefore(corsFilter(), ChannelProcessingFilter.class) 
.and().csrf().disable(); 
} 

Если какая-либо другая информация требуется посетить это -: http://javamusings.com/enabling-cors-support-in-spring-framework/. Примечание: - Я являюсь автором сообщения.