it-swarm.com.de

Federsicherheit CORS Filter

Wir haben Spring Security zu unserem bestehenden Projekt hinzugefügt. 

Von diesem Moment an erhalten wir einen 401 No 'Access-Control-Allow-Origin' header is present on the requested resource Fehler von unserem Server. 

Das liegt daran, dass der Antwort kein Access-Control-Allow-Origin-Header angehängt ist. Um dies zu beheben, haben wir unseren eigenen Filter hinzugefügt, der sich vor dem Logout-Filter in der Kette Filter befindet. Der Filter gilt jedoch nicht für unsere Anfragen.

Unser Fehler:

XMLHttpRequest kann http://localhost:8080/getKunden nicht laden. Auf der angeforderten Ressource ist kein Header "Access-Control-Allow-Origin" vorhanden. Origin http://localhost:3000 ist daher kein Zugriff erlaubt. Die Antwort hatte den HTTP-Statuscode 401.

Unsere Sicherheitskonfiguration:

@EnableWebSecurity
@Configuration
@ComponentScan("com.company.praktikant")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private MyFilter filter;

@Override
public void configure(HttpSecurity http) throws Exception {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();

    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    source.registerCorsConfiguration("/**", config);
    http.addFilterBefore(new MyFilter(), LogoutFilter.class).authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/*").permitAll();
}

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

Unser Filter

@Component
public class MyFilter extends OncePerRequestFilter {

@Override
public void destroy() {

}

private String getAllowedDomainsRegex() {
    return "individual / customized Regex";
}

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

    final String Origin = "http://localhost:3000";

    response.addHeader("Access-Control-Allow-Origin", Origin);
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Headers",
            "content-type, x-gwt-module-base, x-gwt-permutation, clientid, longpush");

    filterChain.doFilter(request, response);

}
}

Unsere anwendung

@SpringBootApplication
public class Application {
public static void main(String[] args) {
    final ApplicationContext ctx = SpringApplication.run(Application.class, args);
    final AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
    annotationConfigApplicationContext.register(CORSConfig.class);
    annotationConfigApplicationContext.refresh();
}
}

Unser Filter ist ab Springboot registriert:

2016-11-04 09: 19: 51.494 INFO 9704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean: Zuordnungsfilter: 'myFilter' auf: [/ *]

Unsere generierte Filterkette:

2016-11-04 09: 19: 52.729 INFO 9704 --- [ost-startStop-1] ossweb.DefaultSecurityFilterChain: Erstellen einer Filterkette: [email protected]1, [org. springfrack.securi[email protected]5d8c5a8a, org.springframework.securi[email protected]7d6938f, org.springframework.security.web. [email protected], [email protected], org.[email protected]2330834f, org.springframework.security.web.savedrequest.Rach. springframework.[email protected]4fc0f1a2, org.springfram[email protected]2357120f, Exce ptionTranslationFilter @ 4b8bf1fb, org.springfr[email protected]42063cf1]

Die Antwort: Antwortheader

Wir haben die Lösung auch aus dem Frühjahr probiert, aber es hat nicht funktioniert! Die Annotation @CrossOrigin in unserem Controller hat auch nicht geholfen.

Edit 1:

Versuchte die Lösung von @Piotr Sołtysiak. Der cors-Filter ist nicht in der generierten Filterkette aufgeführt und wir erhalten immer noch den gleichen Fehler.

2016-11-04 10: 22: 49.881 INFO 8820 --- [ost-startStop-1] ossweb.DefaultSecurityFilterChain: Erstellen einer Filterkette: [email protected]1, [org. springfrachet[email protected]4c191377, org.spring[email protected]28bad32a, org.springframework.secur.web.header.Headerrrrrrrrrrrrrrrrr. [email protected], org.[email protected]1c9cd096, org.springframework.s[email protected]3990c331, org. DefaultLoginPageGeneratingFilter @ 1e8d4ac1, org.springfram[email protected]2d61.b2a4, org.springframework.security.web.savedrequest.RequestCacheAwareFilter @ rAwareRequestFilter @ abf2de3, org.ruhringfram[email protected]2a5c161b, org.springframework.security.web.sessi[email protected], org. [email protected]]

Übrigens verwenden wir die Federsicherheitsversion 4.1.3.!

15
M. Thiele

Ok, nach über zwei Tagen der Suche haben wir das Problem behoben. Wir haben alle unsere Filter und Konfigurationen gelöscht und stattdessen diese 5 Zeilen Code in der Anwendungsklasse verwendet.

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

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedOrigins("http://localhost:3000");
        }
    };
}
}
11
M. Thiele

Seit Spring Security 4.1 ist dies der richtige Weg, um Spring Security CORS zu unterstützen (wird auch in Spring Boot 1.4/1.5 benötigt):

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
    }
}

und:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.csrf().disable();
        http.cors();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH"));
        // setAllowCredentials(true) is important, otherwise:
        // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
        configuration.setAllowCredentials(true);
        // setAllowedHeaders is important! Without it, OPTIONS preflight request
        // will fail with 403 Invalid CORS request
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Tun Sie nichts , was der falsche Weg ist, um das Problem zu lösen:

  • http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
  • web.ignoring().antMatchers(HttpMethod.OPTIONS);

Referenz: http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html

61
Hendy Irawan

Da ich Probleme mit den anderen Lösungen hatte (vor allem, damit es in allen Browsern funktioniert, erkennt Edge beispielsweise "*" nicht als gültigen Wert für "Access-Control-Allow-Methods"), musste ich einen benutzerdefinierten Wert verwenden Filter Component, die am Ende für mich gearbeitet hat und genau das gemacht hat, was ich erreichen wollte.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
    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", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods",
                "ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, Key, Authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    public void init(FilterConfig filterConfig) {
        // not needed
    }

    public void destroy() {
        //not needed
    }

}
8
  1. Sie brauchen nicht:

    @Configuration
    @ComponentScan("com.company.praktikant")
    

    @EnableWebSecurity enthält bereits @Configuration, und ich kann mir nicht vorstellen, warum Sie @ComponentScan dort ablegen.

  2. Über den CORS-Filter würde ich nur folgendes sagen:

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

    In die SecurityConfiguration-Klasse und entfernen Sie globale Methoden. Sie müssen die Erlaubnis-Orgins, Header und Methoden nicht zweimal festlegen. Vor allem, wenn Sie unterschiedliche Eigenschaften in die Filter- und Federkonfigurationskonfiguration setzen :)

  3. Laut oben ist Ihre "MyFilter" -Klasse redundant.

  4. Sie können diese auch entfernen:

    final AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
    annotationConfigApplicationContext.register(CORSConfig.class);
    annotationConfigApplicationContext.refresh();
    

    Aus der Anwendungsklasse.

  5. Am Ende kleiner Rat - nicht mit der Frage verbunden. Sie möchten keine Verben in URI einfügen. Anstelle von http://localhost:8080/getKunden sollten Sie die HTTP-GET-Methode für http://localhost:8080/kunden-Ressource verwenden. Best Practices für das Design von RESTful-API erfahren Sie hier: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

7

Mit Spring Security in Spring Boot 2 können Sie CORS global konfigurieren (z. B. alle Entwicklungsanforderungen aktivieren).

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

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors()
            .and().authorizeRequests()
            .anyRequest().permitAll()
            .and().csrf().disable();
}
4
GKislin

Gemäß der CORS-Filterdokumentation :

"Spring MVC bietet eine fein abgestimmte Unterstützung für die CORS-Konfiguration .__ durch Annotationen auf Controllern. Wenn jedoch mit Spring Verwendet wird, ist es ratsam, sich auf den eingebauten CorsFilter zu verlassen, der bestellt werden muss .__ vor der Filterkette von Spring Security "

So etwas erlaubt GET den Zugriff auf den /ajaxUri:

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import Java.util.Arrays;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AjaxCorsFilter extends CorsFilter {
    public AjaxCorsFilter() {
        super(configurationSource());
    }

    private static UrlBasedCorsConfigurationSource configurationSource() {
        CorsConfiguration config = new CorsConfiguration();

        // origins
        config.addAllowedOrigin("*");

        // when using ajax: withCredentials: true, we require exact Origin match
        config.setAllowCredentials(true);

        // headers
        config.addAllowedHeader("x-requested-with");

        // methods
        config.addAllowedMethod(HttpMethod.OPTIONS);
        config.addAllowedMethod(HttpMethod.GET);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/startAsyncAuthorize", config);
        source.registerCorsConfiguration("/ajaxUri", config);
        return source;
    }
}

Natürlich muss Ihre SpringSecurity-Konfiguration den Zugriff auf den URI mit den aufgelisteten Methoden ermöglichen. Siehe @Hendy Irawan Antwort.

3
lmiguelmh

An vielen Stellen sehe ich die Antwort, die diesen Code hinzufügen muss: 

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

in meinem Fall löst es jedoch eine unerwartete Ausnahme vom Klassentyp aus. corsFilter() bean benötigt den Typ CorsFilter, also habe ich diese Änderungen vorgenommen und diese Definition von bean in meine config gesetzt. Jetzt ist alles in Ordnung.

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}
2
Garik Kalashyan

In meinem Fall habe ich diese Klasse gerade hinzugefügt und @EnableAutConfiguration verwendet

package com.package.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import Java.io.IOException;


 @Component
 public class SimpleCORSFilter extends GenericFilterBean {

/**
 * The Logger for this class.
 */
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public void doFilter(ServletRequest req, ServletResponse resp,
                     FilterChain chain) throws IOException, ServletException {
    logger.info("> doFilter");

    HttpServletResponse response = (HttpServletResponse) resp;
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
    //response.setHeader("Access-Control-Allow-Credentials", "true");
    chain.doFilter(req, resp);

    logger.info("< doFilter");
}

}

2
Alex Fernandez

Für bereits implementierte Programme, die sich Codeänderungen nicht leisten können (z. B. Federsicherheit hinzufügen/aktualisieren), ist das Hinzufügen eines einfachen Proxy eine Lösung: https://stackoverflow.com/a/49827300/1758194

0
Orvyl