CORS mit Federstiefel und eckigen Js funktionieren nicht

87

Ich versuche, REST-Endpunkte für eine Anwendung (Spring-Boot-Anwendung) von einer anderen (anglejs) aufzurufen. Die Anwendungen werden auf den folgenden Hosts und Ports ausgeführt.

  • REST-Anwendung mit Spring Boot, http://localhost:8080
  • HTML-Anwendung mit anglejs, http://localhost:50029

Ich benutze auch spring-securitymit der Spring-Boot-Anwendung. Über die HTML-Anwendung kann ich mich bei der REST-Anwendung authentifizieren, danach kann ich jedoch immer noch nicht auf einen REST-Endpunkt zugreifen. Zum Beispiel habe ich einen AngularJS-Dienst wie folgt definiert.

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

Der AngleJS-Controller sieht wie folgt aus.

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!');
            });
    };
}]);

Beim Anruf http://localhost:8080/api/admin/isloggedinbekomme ich eine 401 Unauthorized.

Auf der Seite der REST-Anwendung habe ich einen CORS-Filter, der wie folgt aussieht.

@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 { }
}

Meine Federsicherheitskonfiguration sieht wie folgt aus.

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

Die Handler schreiben lediglich eine JSON-Antwort, die darauf {success: true}basiert, ob sich der Benutzer angemeldet, nicht authentifiziert oder abgemeldet hat. Das RestAuthenticationEntryPointsieht wie folgt aus.

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

}

Irgendwelche Ideen, was mir fehlt oder was ich falsch mache?

Jane Wayne
quelle
Ich nehme an, Sie müssen auch die Authentifizierung tragen, wie ein Token oder so. Sie haben 2 Server. Hast du dir dieses Tutorial angesehen? spring.io/guides/tutorials/spring-security-and-angular-js
Gokhan Oner
@GokhanOner Wie trage ich die Authentifizierung? Das ist wahrscheinlich das fehlende Teil dieses Problems. Ja, ich habe diese Tutorials durchgesehen und nicht gedacht, dass sie mit meinem Ansatz übereinstimmen. Die ersten beiden Teile befassten sich mit der Http-Basic-Authentifizierung, dann der dritte Teil mit Redis (ich wollte oder wollte das nicht als Abhängigkeit erhalten), und dann ging es im letzten Tutorial um die API Gatewaymit Spring Cloud, was ich für einen Overkill hielt .
Jane Wayne
Ich nehme an, Sie können es ohne die Redis tun, es ist nur ein Schlüsselwert-Cache-Speicher. Sie müssen die Authentifizierung und das CSRF-Token in einem Geschäft speichern, das innerhalb der Karte im laufenden Betrieb möglich ist. Der Schlüssel hier ist der Authentifizierungsschlüssel. Schauen Sie sich das Beispiel an: github.com/dsyer/spring-security-angular/tree/master/… und die Seite mit "Ressourcenserver". Sie werden einige zusätzliche Beans definiert sehen, die Reihenfolge des CORS-Filters ist ebenfalls wichtig. Und einige Requisiten. Änderungen auch notwendig.
Gokhan Oner
Ok, ich habe schnell recherchiert. Alles, was Sie brauchen, um Redis loszuwerden, ist, eine springSessionRepositoryFilter-Bohne zu kisten, siehe github.com/spring-projects/spring-session/blob/1.0.0.RC1/… und auch sessionRepository-Bohne und in dieser Bohne. Anstelle von RedisOperationsSessionRepository können Sie MapSessionRepository verwenden, das sich ebenfalls in der Frühjahrssitzung befindet. Und dann folge dem Beispiel.
Gokhan Oner

Antworten:

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() {
}

}

Sie müssen diesen Filter nicht extra definieren, sondern nur diese Klasse hinzufügen. Der Frühling wird gescannt und für Sie hinzugefügt. SimpleCORSFilter. Hier ist das Beispiel: Spring-Enable-Cors

abosancic
quelle
Ein paar Fragen. 1) Wo soll ich die String-Konstanten setzen HEADERSund X_REDIRECT_LOCATION_HEADER? 2) Ist die Zeile request.getRequestURL());ein Tippfehler oder ein Fehler beim Kopieren / Einfügen? 3) Warum suchen Sie nicht nach OPTIONSder Filterkette und fahren einfach fort?
Jane Wayne
2
Aber es blockiert, um AuthenticationEntryPoint auszuführen. Bitte führen
Pra_A
1
Vielen Dank, es hat mir in meinem Kampf um Frühling und Glut sehr geholfen, zusammenzuarbeiten. Prost Kumpel!
Tomasz Szymanek
FindBugs mag es nicht, einen Header-Parameter zu setzen mit: request.getHeader("Origin")wie oben gezeigt wegen der Aufteilung
Glenn
3
Wenn Ihre Anwendung andere Filter enthält, muss dieser Filter von höchster Priorität sein, indem Sie den Filter mit Anmerkungen versehen @Order(Ordered.HIGHEST_PRECEDENCE) .
Shafiul
42

Ich war in eine ähnliche Situation geraten. Nach Recherchen und Tests sind hier meine Ergebnisse:

  1. Bei Spring Boot wird empfohlen, globales CORS zu aktivieren, indem Sie es in Spring MVC deklarieren und mit einer detaillierten @CrossOriginKonfiguration kombinieren :

    @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. Da Sie jetzt Spring Security verwenden, müssen Sie CORS auch auf Spring Security-Ebene aktivieren, damit es die auf Spring MVC-Ebene definierte Konfiguration nutzen kann als:

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

    Hier finden Sie ein hervorragendes Tutorial, in dem die CORS-Unterstützung im Spring MVC-Framework erläutert wird.

Yogen Rai
quelle
3
ups es funktioniert mit dieser Änderung http .csrf () .disable () .cors () .and ()
marti_
1
@Osgux gut zu hören, dass :) da ich JWT für die Autorisierung benutze und sie csrf-sicher sind, habe ich das nicht dort platziert .. vergessen Sie nicht zu stimmen, wenn es geholfen hat :)
Yogen Rai
Ja, ich habe +1 = D
marti_
@Marcel welches Problem bekommst du?
Yogen Rai
Fehler beim Laden von <meine Restadresse>: Die Antwort auf die Preflight-Anforderung besteht die Zugriffssteuerungsprüfung nicht: In der angeforderten Ressource ist kein Header "Zugriffssteuerung-Zulassen-Ursprung" vorhanden. Origin ' localhost: 8090 ' ist daher kein Zugriff gestattet.
Marcel
22

Wenn Sie CORS ohne Verwendung von Filtern oder ohne Konfigurationsdatei aktivieren möchten, fügen Sie einfach hinzu

@CrossOrigin

an die Spitze Ihres Controllers und es funktioniert.

Eduardo Dennis
quelle
4
Was sind die Sicherheitsrisiken bei diesem Ansatz?
Balaji Vignesh
Ich habe für mich gearbeitet und versucht, Header direkt zur Antwort hinzuzufügen, aber es hat nicht funktioniert, da Preflight nicht behandelt wurde. Ich denke, dies ist nicht gesichert, aber möglicherweise werden einige interne Apps verwendet.
Amisiuryk
Hat für mich gearbeitet. ziemlich praktische Lösung für die interne Anwendung.
Ajay Kumar
8

Wenn Sie über eine Spring-Boot-REST-Dienstanwendung (nicht Spring MVC) mit Spring-Sicherheit verfügen, reicht es aus, CORS über Spring-Sicherheit zu aktivieren (wenn Sie Spring MVC verwenden, kann die Verwendung einer WebMvcConfigurervon Yogen erwähnten Bean die Verwendung einer Bean sein) Der Weg, den Spring Security gehen muss, wird an die darin erwähnte CORS-Definition delegiert.

Sie benötigen also eine Sicherheitskonfiguration, die Folgendes ausführt:

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

}}

Dieser Link enthält weitere Informationen dazu: https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors

Hinweis:

  1. Das Aktivieren von CORS für alle Ursprünge (*) für eine von einem Produkt bereitgestellte Anwendung ist möglicherweise nicht immer eine gute Idee.
  2. CSRF kann ohne Probleme über die Spring HttpSecurity-Anpassung aktiviert werden
  3. Wenn Sie die Authentifizierung in der App mit Spring aktiviert haben ( UserDetailsServicez. B. über a ), configuration.setAllowCredentials(true);muss die hinzugefügt werden

Getestet auf Spring Boot 2.0.0.RELEASE (dh Spring 5.0.4.RELEASE und Spring Security 5.0.3.RELEASE)

Deepak
quelle
Dies löste mein Problem. Als ich neu bei Spring und Spring Boot war, wurde mir klar, dass ich nicht mit Sring MVC baute. Ich hatte einen Vue.js-Client. Andere Antworten schienen für Spring MVC zu sein, aber diese Antwort passte gut zu meiner bereits implementierten Authentifizierung und Autorisierung.
Jaletechs
Hallo @jaletechs, ich verwende auch nuxtJs (ein vuejs-Framework), aber wenn es darum geht, Cookies zu setzen, funktioniert es nicht. Würden Sie so freundlich sein, Ihnen dabei zu helfen?
KAmit
6

spring boot 2.1.0Ich benutze und was für mich funktioniert hat war

A. Fügen Sie cors-Zuordnungen hinzu, indem Sie:

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

B. Fügen Sie die folgende Konfiguration zu meiner HttpSecurityfür die Federsicherheit hinzu

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

Auch im Fall eines Zuul-Proxys können Sie diesen STATT A und B verwenden (nur verwenden HttpSecurity.cors(), um ihn in Spring Security zu aktivieren):

@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);
}
Sep GH
quelle
neuen CorsFilter (Quelle) zurückgeben; nicht so ein Konstruktorfehler
Aadam
@Aadam Verwenden Sie dieselbe Version von Spring Boot wie ich?
Sep GH
2.1.5 wird verwendet
Aadam
@Aadam Das könnte leider der Grund sein.
Sep GH
@Aadam Bitte stellen Sie sicher, dass Sie CorsFilter von verwenden org.springframework.web.filter.CorsFilter. Ich hatte das gleiche Problem, als ich es versehentlich aus Catalina-Paketen verwendet habe.
Sep GH
5

Das funktioniert bei mir:

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

      //...

   }

   //...

}
Renan Polisciuc
quelle
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Adriano Martins
1
Wenn die Authentifizierung über die Spring-Sicherheit aktiviert ist, wird config.setAllowCredentials (true) verwendet. MUSS gesetzt werden, sonst
Deepak
2

Für mich war das einzige, was 100% funktionierte, wenn die Federsicherheit verwendet wurde, das Überspringen aller zusätzlichen Flusen zusätzlicher Filter und Bohnen und aller indirekten "magischen" Leute, die immer wieder vorschlugen, dass dies für sie funktionierte, aber nicht für mich.

Erzwingen Sie stattdessen einfach, die benötigten Header mit einer Ebene zu schreiben 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"));
    }
}

Dies ist der direkteste und expliziteste Weg, den ich gefunden habe. Hoffe es hilft jemandem.

Jeronimo Backes
quelle
1

Schritt 1

Durch Annotieren des Controllers mit @CrossOriginAnnotation werden die CORS-Konfigurationen ermöglicht.

@CrossOrigin
@RestController
public class SampleController { 
  .....
}

Schritt 2

Spring hat bereits einen CorsFilter, obwohl Sie einfach Ihren eigenen CorsFilter als Bean registrieren können, um Ihre eigene Konfiguration wie folgt bereitzustellen.

@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);
}
Saveendra Ekanayake
quelle
0

Überprüfen Sie dieses:

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    ...
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
    ...
}
yibourkelidrissi
quelle
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Rollstuhlfahrer
0

Das Erweitern der WebSecurityConfigurerAdapter-Klasse und das Überschreiben der configure () -Methode in Ihrer @ EnableWebSecurity-Klasse würde funktionieren: Unten finden Sie eine Beispielklasse

@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();
        }
    });
   }
}
keyRen
quelle
0

Wenn Ihr Programm ursprünglich keine Federsicherheit verwendet und sich eine Codeänderung nicht leisten kann, kann das Erstellen eines einfachen Reverse-Proxys den Trick tun. In meinem Fall habe ich Nginx mit der folgenden Konfiguration verwendet:

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

Mein Programm hört : 8080 .

REF: CORS auf Nginx

Orvyl
quelle
0

Das hat bei mir funktioniert.

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

}
Dennis Crissman II
quelle
0

Diese Antwort kopiert die @ abosancic-Antwort, bietet jedoch zusätzliche Sicherheit, um einen CORS-Exploit zu vermeiden .

Tipp 1: Geben Sie den eingehenden Ursprung nicht unverändert wieder, ohne die Liste der zulässigen Hosts für den Zugriff zu überprüfen.

Tipp 2: Zulassen von Anforderungen mit Anmeldeinformationen nur für Hosts auf der Whitelist.

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;
        }
    }
}
Shailesh Pratapwar
quelle
0

In unserer Spring Boot-App haben wir CorsConfigurationSource wie folgt eingerichtet.

Durch die Reihenfolge des allowedOrignserstmaligen Hinzufügens und anschließenden Einstellens kann applyPermitDefaultValues()Spring Standardwerte für zulässige Header, exponierte Header, zulässige Methoden usw. einrichten, sodass wir diese nicht angeben müssen.

    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);
    }
Treffen Sie Shah
quelle
0

Machen Sie einfach eine einzelne Klasse wie, alles wird gut damit:

        @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 {
            }
        }
Imranmadbar
quelle
0

Dies hat bei mir funktioniert, um CORS zwischen Spring Boot und React zu deaktivieren

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

Ich musste die Sicherheitskonfiguration auch wie folgt ändern:

        @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());
        }
Gil Nz
quelle