Настройка Spring для CORS

Я пытаюсь настроить Spring для CORS, чтобы использовать веб-интерфейс Angular:

Я пробовал это:

@Configuration
@ComponentScan("org.datalis.admin.config")
public class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
        PropertySourcesPlaceholderConfigurer conf = new PropertySourcesPlaceholderConfigurer();
        conf.setLocation(new ClassPathResource("application.properties"));
        return conf;
    }

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("127.0.0.1");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

Сервер Apache с Angular FE работает с сервером Wildly на том же сервере, поэтому я настроил 127.0.0.1 в качестве источника.

Но все же я получаю:

Access to XMLHttpRequest at 'http://123.123.123.123:8080/api/oauth/token' from origin 'http://123.123.123.123' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
auth:1 Failed to load resource: the server responded with a status of 404 (Not Found)

Вы знаете, как я могу решить эту проблему?

Второй способ, который я пробовал:

@Configuration
@EnableResourceServer
public class ResourceSecurityConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId("resource_id").stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/users/**").permitAll()
                .anyRequest().authenticated()
                .and()
        .cors().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
        .anyRequest()
        .fullyAuthenticated()
        .and()
        .httpBasic()
        .and()
        .csrf().disable();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSources() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
        configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Со второй конфигурацией получаю has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status. auth:1 Failed to load resource: the server responded with a status of 404 (Not Found)

Как лучше всего достичь этого результата?

В качестве примечания вы можете рассмотреть возможность установки приоритета bean.setOrder(Ordered.HIGHEST_PRECEDENCE) вместо нуля.

Roddy of the Frozen Peas 18.01.2019 17:33

Теперь я получаю, что в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin».

Peter Penzov 18.01.2019 17:38
stackoverflow.com/a/53863603/10426557
Jonathan JOhx 18.01.2019 20:18

@JonathanJohx Я получаю доступ к XMLHttpRequest в «123.123.123.123:8080/API/Oauth/токен» из источника «123.123.123.123» заблокирован политикой CORS: ответ на предварительный запрос не проходит проверку контроля доступа: он не имеет статуса HTTP ok.

Peter Penzov 18.01.2019 20:29

Есть еще предложения как это исправить?

Peter Penzov 19.01.2019 09:25
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
9
5
1 846
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Вам нужно добавить уровень класса @CrossOrigin в класс вашего контроллера, как показано ниже.

@CrossOrigin
public class SampleController {
    // Your code goes here
}

аннотация к вашему классу контроллера отдыха

Ваш разрешенный источник — 127.0.0.1, но ваша клиентская сторона имеет IP-адрес 123.123.123.123. Попробуйте изменить это:

config.addAllowedOrigin("127.0.0.1");

К этому:

config.addAllowedOrigin("123.123.123.123");

Привет Рафаэль! Добро пожаловать в StackOverflow. Я отредактировал ваш пост, чтобы отформатировать код - для дальнейшего использования блоки кода форматируются с отступом в четыре пробела.

Roddy of the Frozen Peas 18.01.2019 17:34

Вы можете попробовать добавить на свой клиент заголовок «с учетными данными: true». Вы можете сделать это на угловом добавлении перехватчика на http-клиенте. См. stackoverflow.com/questions/38615205/…

Raphael Alves 18.01.2019 22:19
Ответ принят как подходящий

Вам нужно сообщить Spring Security, чтобы он использовал созданную вами конфигурацию CORS.

В своем проекте я настроил Spring Security следующим образом:

@Override
protected void configure(HttpSecurity http) throws Exception
{
    http
        .authorizeRequests()
        .antMatchers("/rest/protected/**")
        .authenticated()
     //Other spring sec configruation and then:
    .and()
        .cors()
        .configurationSource(corsConfigurationSource())

}

Где corsConfigurationSource():

@Bean
    CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        boolean abilitaCors = new Boolean(env.getProperty("templating.oauth.enable.cors"));
        if ( abilitaCors )
        {
            if ( logger.isWarnEnabled() )
            {
                logger.warn("CORS ABILITATI! Si assume ambiente di sviluppo");
            }
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200","http://localhost:8080", "http://localhost:8180"));
            configuration.setAllowedMethods(Arrays.asList(  RequestMethod.GET.name(),
                    RequestMethod.POST.name(), 
                    RequestMethod.OPTIONS.name(), 
                    RequestMethod.DELETE.name(),
                    RequestMethod.PUT.name()));
            configuration.setExposedHeaders(Arrays.asList("x-auth-token", "x-requested-with", "x-xsrf-token"));
            configuration.setAllowedHeaders(Arrays.asList("X-Auth-Token","x-auth-token", "x-requested-with", "x-xsrf-token"));
            source.registerCorsConfiguration("/**", configuration);
        }
        return source;
    }

Я надеюсь, что это полезно

Анджело

Я снова получаю доступ к XMLHttpRequest на 'http://123.123.123.123:8080/api/oauth/token' from origin 'http://123.123.123.123' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.. Любые другие идеи?

Peter Penzov 21.01.2019 09:58

Из того, что я вижу, я понимаю, что: вы должны настроить источник cors с IP-адресом 123.123.123.123 больше, чем через AJAX. Вы также добавили IP-адрес? Вы изменили CorsConfigurationSource, добавив правильный IP-адрес? Включите весенние журналы безопасности TRACE

Angelo Immediata 21.01.2019 10:05

В вашем файле logback.xml добавьте регистратор Spring, подобный этому <logger name = "org.springframework.security" level = "TRACE"></logger>.

Angelo Immediata 21.01.2019 15:10

ок, попробую позже. Вы видите проблемы в моей конфигурации Spring-boot/Spring Security?

Peter Penzov 21.01.2019 15:14

Я не эксперт по загрузке Spring, но мне кажется, что все в порядке, за исключением того факта, что cors config закомментирован

Angelo Immediata 21.01.2019 16:27

Насколько я вижу, ваш IP-адрес 212.75.28.84; вы тоже настроили этот IP-адрес?

Angelo Immediata 22.01.2019 08:40

Это мой домашний IP. Я не думаю, что мне нужно добавлять его в CORS.

Peter Penzov 22.01.2019 08:43

Ну, вы должны. Это IP-адрес, который пытается вызвать REST API.

Angelo Immediata 22.01.2019 08:44

хорошо, но в производство я могу добавить каждого конечного клиента в конфигурацию CORS. Попробуем добавить *?

Peter Penzov 22.01.2019 08:50

В производстве вы НЕ ДОЛЖНЫ добавлять никаких исключений. Вам следует настроить веб-сервер Apache так, чтобы он обслуживал все запросы в одном и том же домене, в противном случае вы рискуете очень серьезными хакерскими атаками; по этой причине в моем коде у меня есть переменная свойств

Angelo Immediata 22.01.2019 09:01

Давайте сосредоточимся на этом? Если я настрою Apache для обслуживания всех запросов в одном домене, нужно ли мне настраивать CORS в Spring?

Peter Penzov 22.01.2019 09:04

Нет, вы не должны настраивать CORS. Согласно JS, все запросы имеют одно и то же происхождение, и все их можно обслуживать безопасно.

Angelo Immediata 22.01.2019 09:05

хорошо, я попробую это тогда. Еще один вопрос: что, если я запущу приложение Angular на сервере apache, а не на клиентской машине? (Классическое приложение, обслуживаемое постранично с сервера)

Peter Penzov 22.01.2019 09:10

Я думаю, что это лучше всего сделать... Обычно я делаю так... все статические ресурсы, обслуживаемые Apache

Angelo Immediata 22.01.2019 09:11

ок, сегодня проверю и сообщу. Можете ли вы рассказать больше о том, как вы используете Angular? (Настройка сервера и т. д.)

Peter Penzov 22.01.2019 09:15

Вы решили проблему, настроив веб-сервер?

Angelo Immediata 23.01.2019 14:22

нет, Angular по какой-то причине не может использовать Apache в качестве прокси.

Peter Penzov 23.01.2019 14:40

Я добавил описание здесь: stackoverflow.com/questions/54331671/…

Peter Penzov 23.01.2019 17:29

Это мой рабочий класс @Configuration для обработки запросов CORS, используемых только в среде разработки.

@Configuration
//@Profile(PROFILE_DEV)
  public class CorsConfiguration {

  @Bean
  public WebMvcConfigurer corsConfigurer() {
      return new WebMvcConfigurer() {
          @Override
          public void addCorsMappings(CorsRegistry registry) {
              registry.addMapping("/**")
                  .allowedOrigins("*")
                  .allowedHeaders("*")
                  .allowedMethods("*");
          }
      };
  }
}

Вы также должны настроить Spring Security для игнорирования HttpMethod.OPTIONS, используемого предварительным запросом (в качестве исключения, которое вы упомянули)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  //...
    @Override
    public void configure(WebSecurity web) throws Exception {
      web.ignoring()
            //others if you need
            .antMatchers(HttpMethod.OPTIONS, "/**");

    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
            .disable()
            .exceptionHandling()
            .and()
            .headers()
            .frameOptions()
            .disable()
            .and()
            .authorizeRequests()
            .antMatchers("/api/register").permitAll()
            .antMatchers("/api/activate").permitAll()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/**").authenticated();
    }

}

Потому что, когда вы используете cors, у вас есть Простой запрос и Предварительный запрос, которые запускают HttpMethod.OPTIONS.

Я также использую безопасность Spring. Будет ли это работать для Spring Security?

Peter Penzov 21.01.2019 10:13

обновленный ответ с настройкой Spring Security OPTIONS

ValerioMC 21.01.2019 10:38

Я попробовал ваше предложение в сочетании с предложением от @Angelo Immediata, но все равно получаю ту же проблему. Любая дополнительная идея, как ее решить?

Peter Penzov 21.01.2019 11:49

Моему решению не нужно добавлять другие вещи. Попробуйте оставить код, как я объяснил, просто убедитесь, что классы @Configuration правильно загружены. Скажите, если у вас все еще есть исключение

ValerioMC 21.01.2019 12:01

Я тестировал только ваш код. К сожалению, проблема не устранена.

Peter Penzov 21.01.2019 12:06

Могу ли я увидеть ваши классы конфигурации?

ValerioMC 21.01.2019 12:13

Сегодня я загружу на GitHub минимальный рабочий пример.

Peter Penzov 21.01.2019 12:22

Я добавил сюда свою конфигурацию: github.com/rcbandit111/Spring_test

Peter Penzov 21.01.2019 14:47

это хорошо, потому что теперь конфигурация CORS работает, но по какой-то причине `web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");` не принимается... Теперь у вас есть 403 FORBIDDEN на предварительном запросе. Вам нужно разрешить весеннюю безопасность всем вашим методам OPTIONS

ValerioMC 21.01.2019 21:16

Я пытался добавить это: http .csrf().disable() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS,"/**").permitAll() Но теперь я получаю Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Peter Penzov 21.01.2019 21:47

удалить .antMatchers(HttpMethod.OPTIONS,"/**").permitAll() и оставить конфигурацию OPTIONS только в классе CorsConfiguration

ValerioMC 21.01.2019 22:31

Я получаю во время развертывания: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalStateException: At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated()) Можете ли вы немного расширить то, что мне нужно установить для HttpSecurity http

Peter Penzov 21.01.2019 22:40

Давайте продолжить обсуждение в чате.

ValerioMC 21.01.2019 22:49

Я рекомендую вам использовать WebMvcConfigurer и в методе addCorsMappings установить конфигурацию CORS.

Что-то вроде этого

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("http://localhost:9798")
            .allowedMethods("POST", "GET")
            //.allowedHeaders("header1", "header2", "header3")
            //.exposedHeaders("header1", "header2")
            .allowCredentials(true).maxAge(3600);
    }
}

Здесь есть ссылка на полнофункциональный проект Spring with CORS, просто скачайте и запустите его.

https://github.com/reos79/spring-cors

У него есть html-страница (person.html), эта страница ничего не делает, кроме вызова службы на порту (9797). Таким образом, вам нужно загрузить этот проект дважды, один раз на порт 9797 для загрузки службы, а другой — на порт (9798). Затем в вашем браузере вы вызываете человека страницы на сервере localhost: 9798, и он вызывает службу на локальном хосте: 9797, в файле application.properties я настроил порт.

знаете ли вы, что мне нужно добавить некоторые настройки в Apache и Angular?

Peter Penzov 21.01.2019 18:25

Вот файл конфигурации Wildfly, использующий вашу конфигурацию: pastebin.com/TzXPsNwt

Peter Penzov 21.01.2019 19:48

Вы удалили общедоступный CorsConfigurationSource corsConfigurationSources() Bean? и Bean public FilterRegistrationBean<CorsFilter> corsFilter() ?

reos 21.01.2019 20:26

Да, я сделал. Но я попробую еще раз с чистой настройкой позже.

Peter Penzov 21.01.2019 20:27

Вот результат второй попытки: pastebin.com/q5eRqSz8

Peter Penzov 21.01.2019 21:56

Я пропустил это в своем коде: http .cors().and() .csrf().disable() .authorizeRequests().anyRequest().permitAll() .and().authorizeRequests() .antMatchers("/users/**").permitAll() .anyRequest().authenticated();

Peter Penzov 21.01.2019 22:06

Это связано с проблемами аутентификации, замените свой метод этим, просто чтобы попробовать Override protected void configure(HttpSecurity http) throws Exception { http .cors().and() .csrf().disable() .authorizeRequests().anyRequest ().разрешитьвсе(); }

reos 21.01.2019 22:44

Нет положительного результата.

Peter Penzov 21.01.2019 22:53

это сложно, потому что у меня нет вашего полного проекта. Проект, который я вам дал, просто работает, вам не нужен сервер приложений или что-то еще, он просто работает. Я предлагаю вам сравнить оба проекта и посмотреть, что отличается

reos 21.01.2019 22:56

Попробуйте изменить имя компонента на corsConfigurationSource, удалив букву «s».

Документация https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors

// by default uses a Bean by the name of corsConfigurationSource

Другие вопросы по теме