Вопрос:

Как настроить CORS в приложении Spring Boot + Spring Security?

javascript spring spring-security spring-boot cors

96543 просмотра

13 ответа

607 Репутация автора

Я использую Spring Boot с Spring Security и Cors Support.

Если я выполню следующий код

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:a'
do xmlhttp.send

Я получаю в результате

200

Если я проверю с неправильными учетными данными, такими как

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:aa'
do xmlhttp.send

вместо 401 (это стандартный код для неправильной аутентификации в весенней безопасности) я получаю

0

со следующим уведомлением браузера:

ПОЛУЧИТЕ http: // localhost: 5000 / api / token

XMLHttpRequest не может загрузить http: // localhost: 5000 . В запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Поэтому происхождение ' http: // localhost: 3000 ' не разрешено. Ответ имел HTTP-код состояния 401.

Я разрабатываю код переднего плана, которому нужны полезные коды состояния http из ответов сервера, чтобы справиться с ситуацией. Мне нужно что-то более полезное, чем 0. Также тело ответа пусто. Я не знаю, если мой конфиг неправильный, или это программная ошибка, и я также не знаю, где, если это хром (с использованием Arch Linux) или Spring Security.

Мой Spring Config это:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@RestController
@RequestMapping("api")
public class Controller {
    @RequestMapping("token")
    @CrossOrigin
    Map<String, String> token(HttpSession session) {
        return Collections.singletonMap("token", session.getId());
    }
}

@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("a").password("a").roles("USER");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
    }
}

Если я тестирую с помощью curl, все работает отлично, я думаю, что поддержка CORS не требуется, но я попытался смоделировать CORS с запросами OPTION, и результат также был в порядке.

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTpha"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTpha
> 
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Access-Control-Allow-Origin: http://localhost:3000
< Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE
< Access-Control-Max-Age: 3600
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin,Accept,X-Requested-    With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization
< x-auth-token: 58e4cca9-7719-46c8-9180-2fc16aec8dff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:15:44 GMT
< 
* Connection #0 to host localhost left intact
{"token":"58e4cca9-7719-46c8-9180-2fc16aec8dff"}

и с неправильными учетными данными:

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTp"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTp
> 
< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< WWW-Authenticate: Basic realm="Realm"
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:16:15 GMT
< 
* Connection #0 to host localhost left intact
{"timestamp":1462119375041,"status":401,"error":"Unauthorized","message":"Failed to decode basic authentication token","path":"/api/token"}

Изменить: чтобы избежать недоразумений. Я использую 1.3.3 Spring Boot. Сообщение в блоге пишет:

Поддержка CORS будет доступна в следующем выпуске Spring Boot 1.3 и уже доступна в сборках 1.3.0.BUILD-SNAPSHOT.

Использование метода контроллера Настройка CORS с аннотациями @CrossOrigin в приложении Spring Boot не требует какой-либо конкретной настройки.

Глобальная конфигурация CORS может быть определена путем регистрации bean-компонента WebMvcConfigurer с помощью настроенного метода addCorsMappings (CorsRegistry):

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

@Configuration
public class MyConfiguration {

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

Идея, что проблема возникает из-за перенаправления между процессами авторизации, интересна. Как я могу изменить перенаправление на любые ресурсы, чтобы избежать этого конфликта?

РЕДАКТИРОВАТЬ:

Я думаю, что я ближе к решению. Я проверил на своем сервере nodejs, который поддерживает cors без проблем, добавив Access-Control-Allow-Origin: * ко всем запросам.

Как уже упоминал Стефан Изеле, кажется, что весенняя система безопасности перенаправляет или не добавляет заголовок CORS, поэтому запрос кажется неработоспособным. Таким образом, пока весенняя безопасность проверяет аутентификацию, она должна добавить правильный заголовок.

Кто-нибудь знает как это сделать?

РЕДАКТИРОВАТЬ:

Я нашел обходной путь, который кажется уродливым. Я начал проблему с github для весенней загрузки, где я опишу обходной путь: https://github.com/spring-projects/spring-boot/issues/5834

Автор: Rudolf Schmidt Источник Размещён: 01.05.2016 04:23

Ответы (13)


8 плюса

5311 Репутация автора

Защита от перекрестного происхождения - это особенность браузера. Curl не заботится о CORS, как вы предполагали. Это объясняет, почему ваши кудри успешны, а запросы браузера - нет.

Если вы отправите запрос браузера с неправильными учетными данными, Spring попытается перенаправить клиента на страницу входа. Этот ответ (вне страницы входа в систему) не содержит заголовка «Access-Control-Allow-Origin», и браузер реагирует так, как вы описываете.

Вы должны сделать пружину, чтобы включить хэдер для этого ответа на вход в систему, и может быть для другого ответа, такого как страницы ошибок и т. Д.

Это можно сделать так:

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                    .allowedOrigins("http://domain2.com")
                    .allowedMethods("PUT", "DELETE")
                    .allowedHeaders("header1", "header2", "header3")
                    .exposedHeaders("header1", "header2")
                    .allowCredentials(false).maxAge(3600);
            }
     }

Это скопировано с Cors-Support-In-Spring-Framework

Я бы начал с добавления Cors Mapping для всех ресурсов:

registry.addMapping("/**")

а также разрешить заголовки для всех методов. Как только это сработает, вы можете начать уменьшать это снова до необходимого минимума.

Обратите внимание, что конфигурация CORS меняется с выпуском 4.2.

Если это не решит ваши проблемы, опубликуйте ответ, полученный на неудавшийся запрос ajax.

Автор: Stefan Isele - prefabware.com Размещён: 01.05.2016 05:48

33 плюса

3382 Репутация автора

Spring Security теперь может использовать поддержку Spring MVC CORS, описанную в этом посте, который я написал.

Чтобы это работало, вам нужно явно включить поддержку CORS на уровне Spring Security следующим образом, иначе запросы с включенным CORS могут быть заблокированы Spring Security до достижения Spring MVC.

Если вы используете @CrossOriginаннотации на уровне контроллера , вам просто нужно включить поддержку Spring Security CORS, и она будет использовать конфигурацию Spring MVC:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()...
    }
}

Если вы предпочитаете использовать глобальную конфигурацию CORS, вы можете объявить CorsConfigurationSourcebean-компонент следующим образом:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }
}

Этот подход заменяет ранее рекомендованный подход на основе фильтров .

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

Автор: Sébastien Deleuze Размещён: 03.06.2016 09:42

14 плюса

429 Репутация автора

Если вы используете 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;
    }
}

См. Spring 4.2.x CORS для получения дополнительной информации.

Автор: Je Suis Alrick Размещён: 06.12.2016 04:28

2 плюса

7259 Репутация автора

Для настройки свойств

# ENDPOINTS CORS CONFIGURATION (EndpointCorsProperties)
endpoints.cors.allow-credentials= # Set whether credentials are supported. When not set, credentials are not supported.
endpoints.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers.
endpoints.cors.allowed-methods=GET # Comma-separated list of methods to allow. '*' allows all methods.
endpoints.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
endpoints.cors.exposed-headers= # Comma-separated list of headers to include in a response.
endpoints.cors.max-age=1800 # How long, in seconds, the response from a pre-flight request can be cached by clients.
Автор: Radouane ROUFID Размещён: 21.05.2017 02:58

2 плюса

6528 Репутация автора

Нашли простое решение для Spring-Boot, Spring-Security и конфигурации на основе Java:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors().configurationSource(new CorsConfigurationSource() {
            @Override
            public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                return new CorsConfiguration().applyPermitDefaultValues();
            }
        });
    }
}
Автор: Hubert Grzeskowiak Размещён: 04.06.2017 05:05

18 плюса

1783 Репутация автора

Если вы используете JDK 8+, существует одно строчное лямбда-решение:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
}
Автор: zhouji Размещён: 15.08.2017 02:38

2 плюса

29 Репутация автора

Я решил эту проблему путем:

@Configuration
public class CORSFilter extends CorsFilter {

    public CORSFilter(CorsConfigurationSource source) {
        super((CorsConfigurationSource) source);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        response.addHeader("Access-Control-Allow-Headers",
                "Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
        if (response.getHeader("Access-Control-Allow-Origin") == null)
            response.addHeader("Access-Control-Allow-Origin", "*");
        filterChain.doFilter(request, response);
    }

}

а также:

@Configuration
public class RestConfig {

    @Bean
    public CORSFilter corsFilter() {
        CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://localhost:4200");
        config.addAllowedMethod(HttpMethod.DELETE);
        config.addAllowedMethod(HttpMethod.GET);
        config.addAllowedMethod(HttpMethod.OPTIONS);
        config.addAllowedMethod(HttpMethod.PUT);
        config.addAllowedMethod(HttpMethod.POST);
        ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**", config);
        return new CORSFilter(source);
    }
}
Автор: Özlem Gürses Размещён: 30.10.2017 06:48

1 плюс

87 Репутация автора

У меня была такая же проблема на методе, который возвращает статус сервера. Приложение развернуто на нескольких серверах. Так что самое простое, что я нашел, это добавить

@CrossOrigin(origins = "*")
@RequestMapping(value="/schedulerActive")
public String isSchedulerActive(){
  //code goes here
}

Этот метод небезопасен, но вы можете добавить allowCredentialsдля этого.

Автор: Khalifa Размещён: 13.11.2017 02:38

2 плюса

31 Репутация автора

Я решил эту проблему:

@Bean
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers","Access-Control-Allow-Origin","Access-Control-Request-Method", "Access-Control-Request-Headers","Origin","Cache-Control", "Content-Type", "Authorization"));
    configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

`

Автор: Toan Truong Размещён: 22.04.2018 10:27

2 плюса

91 Репутация автора

Корс может быть болью в заднице, но с этим простым кодом вы - ТОЛЬКО Корс !!!! к указанному методу

@CrossOrigin(origins="*")// in this line add your url and thats is all for spring boot side
    @GetMapping("/some")
    public String index() {
        return "pawned cors!!!!";
    }

Как брелок в весеннем сапоге 2.0.2

Автор: Andres Navarro Размещён: 15.06.2018 03:19

0 плюса

1 Репутация автора

У меня были серьезные проблемы с Axios, Spring Boot и Spring Security с аутентификацией.

Обратите внимание на версию Spring Boot и Spring Security, которые вы используете.

Spring Boot: 1.5.10 Spring: 4.3.14 Spring Security 4.2.4

Чтобы решить эту проблему с помощью конфигурации Java на основе аннотаций, я создал следующий класс:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth.inMemoryAuthentication()
                .withUser("youruser").password("yourpassword")
                .authorities("ROLE_USER");
    }

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

        http.cors().and().
                authorizeRequests()
                .requestMatchers(CorsUtils:: isPreFlightRequest).permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic()
                .realmName("Biometrix");

        http.csrf().disable();

    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("Authorization"));
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Одним из основных недостатков Axios является то, что когда ваш API требует аутентификации, он отправляет заголовок авторизации с запросом OPTIONS. Если вы не включите Авторизацию в настройке конфигурации разрешенных заголовков, наш запрос OPTIONS (он же PreFlight запрос) завершится неудачно, и Axios сообщит об ошибке.

Как вы можете видеть с помощью пары простых и правильно расположенных настроек, настройка CORS с SpringBoot довольно проста.

Автор: Sami Elhini Размещён: 30.12.2018 06:32

0 плюса

120 Репутация автора

Котлин раствор

...
http.cors().configurationSource {
  CorsConfiguration().applyPermitDefaultValues()
}
...
Автор: Ahmed H. Saab Размещён: 12.06.2019 09:25

0 плюса

1 Репутация автора

После долгих поисков ошибок, возникающих в javascript CORS, единственное элегантное решение, которое я нашел для этого случая, - это настройка коров собственного класса Spring org.springframework.web.cors.CorsConfiguration.CorsConfiguration ().

@EnableWebSecurity

открытый класс WebSecurityConfig расширяет WebSecurityConfigurerAdapter {

@Override защищенный void configure (HttpSecurity http) выдает исключение {http.cors (). ConfigurationSource (запрос -> новый CorsConfiguration (). ApplyPermitDefaultValues ​​()); }

Автор: Phill Monteiro Размещён: 14.06.2019 07:14
Вопросы из категории :
32x32