CORS з пружинним завантаженням і angularjs не працюють


87

Я намагаюся викликати кінцеві точки REST в одній програмі (програмі spring-boot) з іншої (angularjs). Додатки працюють на таких хостах і портах.

  • Додаток REST, використовуючи пружинне завантаження http://localhost:8080
  • Додаток HTML, використовуючи angularjs, http://localhost:50029

Я також використовую spring-securityз додатком spring-boot. За допомогою програми 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);
    }
}

Все, що роблять обробники, - це виписування відповіді JSON, наприклад, {success: true}на основі того, якщо користувач увійшов, не вдалося автентифікуватися або вийшов з системи. У 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хмари з spring, яка, на мою думку, була надмірною .
Jane Wayne

Припускаю, ви можете зробити це без redis, це просто сховище кеш-пам'яті ключ-значення. Вам потрібно зберігати маркер автентифікації та CSRF у магазині, можливо, всередині карти на льоту. Ключовим моментом тут є ключ автентифікації. перегляньте приклад: github.com/dsyer/spring-security-angular/tree/master/… та сторінку з "сервером ресурсів". Ви побачите кілька додаткових компонентів, порядок фільтра CORS також важливий. І якийсь реквізит. зміни також необхідні.
Гохан Онер

Добре, я швидко зробив дослідження. Все, що вам потрібно, щоб позбутися Redis, - це створити боб springSessionRepositoryFilter, загляньте на github.com/spring-projects/spring-session/blob/1.0.0.RC1/… , а також bean sessionRepository і в цьому бобі, замість RedisOperationsSessionRepository, ви можете використовувати MapSessionRepository, який також знаходиться у весняному сеансі. А потім наслідуйте приклад.
Гохан Онер

Відповіді:


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
Щиро дякую, це надзвичайно допомогло мені в моїй боротьбі за те, щоб весна і жар працювали разом. Будьмо, друже!
Томаш Шиманек

FindBugs не любить встановлювати параметр заголовка з: request.getHeader("Origin")як показано вище через розбиття відповіді HTTP
Гленн

3
Якщо у вашій програмі є інші фільтри, цей фільтр повинен мати найвищий пріоритет, анотовуючи фільтр за допомогою @Order(Ordered.HIGHEST_PRECEDENCE) .
Шафіуль,

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, вам також слід увімкнути CORS на рівні Spring Security, щоб дозволити йому використовувати конфігурацію, визначену на рівні MVC Spring, як:

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

    Ось чудовий посібник, що пояснює підтримку CORS у Spring MVC framework.


3
ups це працює з цією зміною http .csrf () .disable () .cors () .and ()
marti_

1
@Osgux приємно це чути :), оскільки я використовую JWT для авторизації, і вони безпечні для csrf, я цього не ставив .. не забудьте проголосувати, якщо це допомогло :)
Йоген Рай,

так, я додав +1 = D
marti_

@Marcel, яке питання ви отримуєте?
Йоген Рай

Не вдалося завантажити <мою адресу відпочинку>: Відповідь на попередній запит не проходить перевірку контролю доступу: На запитуваному ресурсі немає заголовка «Access-Control-Allow-Origin». Таким чином, походження ' localhost: 8090 ' заборонено.
Марсель

22

Якщо ви хочете увімкнути CORS без використання фільтрів або без конфігураційного файлу, просто додайте

@CrossOrigin

у верхній частині вашого контролера, і він працює.


4
Які ризики для безпеки, дотримуючись такого підходу?
Balaji Vignesh

Працював у мене, я намагався додати заголовки безпосередньо у відповідь, але це не спрацювало, оскільки не було оброблено передпольоти. Я думаю, що це не захищено, але можуть використовуватися деякі внутрішні програми.
amisiuryk

Працював у мене. досить зручне рішення для внутрішнього застосування.
Аджай Кумар,

8

Щоб спиратися на інші відповіді вище, у випадку, якщо у вас є сервісний додаток Spring boot REST (не Spring MVC) із Spring security, то достатньо ввімкнення CORS через Spring security (якщо ви використовуєте Spring MVC, тоді використання WebMvcConfigurerкомпонента, як згадано Yogen, може бути шлях, як Spring 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. Увімкнення CORS для всіх джерел (*) для розгорнутого додатка може не завжди бути гарною ідеєю.
  2. CSRF можна увімкнути за допомогою налаштування Spring HttpSecurity без будь-яких проблем
  3. Якщо у вас увімкнено автентифікацію в додатку з Spring (наприклад, за допомогою UserDetailsService), тоді 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), але коли справа доходить до встановлення файлів cookie, він не працює. будь ласка, будь ласка, допоможи у цьому.
KAmit

6

Я використовую, spring boot 2.1.0і те, що мені вдалося, - це

A. Додайте відображення корсів за допомогою:

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

B. Додайте нижче конфігурацію до моєї HttpSecurityдля весняної безпеки

.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 ви можете використовувати це ЗАМЕСТО A та B (просто використовуйте, HttpSecurity.cors()щоб увімкнути його у захисті Spring):

@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);
}

повернути новий CorsFilter (джерело); не така помилка конструктора
Aadam

@Aadam Чи використовуєте ви таку ж версію весняного завантаження, як і я?
вересень GH

2.1.5 використовується
Aadam,

@Aadam Це може бути причиною, на жаль.
вересень GH

@Aadam Будь ласка, переконайтесь, що ви використовуєте CorsFilter від org.springframework.web.filter.CorsFilter. У мене була така сама проблема, коли я випадково використовував її з пакетів каталіни.
вересень 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;
        }
      });

      //...

   }

   //...

}

Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, чому та / або як цей код відповідає на питання, покращує його довгострокове значення.
Адріано Мартінс

1
Якщо автентифікація ввімкнена через Spring security, тоді config.setAllowCredentials (true); ПОВИНЕН ставити інакше запити на CORS все одно будуть невдалими
Діпак

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
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 та перевизначення методу configure () у вашому класі @EnableWebSecurity працювали б: Нижче наведено зразок класу

@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 .

REF: CORS на Nginx


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. Не відображайте вхідне джерело, як є, не перевіряючи список дозволених хостів.

Порада 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

Це те, що мені вдалося, щоб вимкнути CORS між Spring boot і React

@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());
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.