Ich habe ein Problem mit dem CORS-Filter für Spring Security-URLs . Es wird weder Access-Control-Allow-Origin
noch andere exponierte Header auf URLs gesetzt, die zu Springsek (Login/Logout) gehören oder von Spring Security gefiltert werden.
Hier sind die Konfigurationen.
KERN:
@Configuration
@EnableWebMvc
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
********some irrelevant configs************
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT")
.allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
"Access-Control-Request-Headers")
.exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
.allowCredentials(true).maxAge(3600);
}
}
Sicherheit:
@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
.formLogin()
.successHandler(ajaxSuccessHandler)
.failureHandler(ajaxFailureHandler)
.loginProcessingUrl("/authentication")
.passwordParameter("password")
.usernameParameter("username")
.and()
.logout()
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/authentication").permitAll()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')")
.antMatchers("/user/*").access("hasRole('ROLE_USER')");
}
}
Wenn ich also eine Anfrage an die URLs stelle, die nicht von der Sicherheit abgehört werden, werden CORS-Header gesetzt. Spring-Sicherheits-URLs - nicht festgelegt.
Springstiefel 1.4.1
Anstatt CorsRegistry zu verwenden, können Sie Ihren eigenen CorsFilter schreiben und zu Ihrer Sicherheitskonfiguration hinzufügen.
Benutzerdefinierte CorsFilter-Klasse:
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request= (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", true);
response.setHeader("Access-Control-Max-Age", 180);
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
Sicherheitskonfigurationsklasse:
@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean
CorsFilter corsFilter() {
CorsFilter filter = new CorsFilter();
return filter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
.formLogin()
.successHandler(ajaxSuccessHandler)
.failureHandler(ajaxFailureHandler)
.loginProcessingUrl("/authentication")
.passwordParameter("password")
.usernameParameter("username")
.and()
.logout()
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/authentication").permitAll()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')")
.antMatchers("/user/*").access("hasRole('ROLE_USER')");
}
}
Die CORS-Konfiguration, mit der Sie begonnen haben, ist nicht die richtige Methode für Spring Boot. Sie müssen eine WebMvcConfigurer
Bean registrieren. Referenz hier .
Beispiel einer Spring Boot CORS Konfiguration:
@Configuration
@Profile("dev")
public class DevConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200");
}
};
}
}
Dadurch wird die CORS-Konfiguration für eine einfache Spring Boot-Anwendung (ohne Sicherheitsstarter) bereitgestellt. Beachten Sie, dass die CORS-Unterstützung von Spring Security unabhängig ist.
Sobald Sie Spring Security eingeführt haben, müssen Sie CORS mit Ihrer Sicherheitskonfiguration registrieren. Spring Security ist intelligent genug, um Ihre vorhandene CORS-Konfiguration zu übernehmen.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
....
Die erste Option, die ich beschrieben habe, bezieht sich auf das Hinzufügen von Spring Security zu einer vorhandenen Anwendung. Wenn Sie Spring Security von Anfang an hinzufügen, wird in den Spring Security Docs eine CorsConfigurationSource-Bean hinzugefügt.
@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;
}
}
Ich habe einen React
-basierten Web-Client, und meine Backend-API REST führt Spring Boot
Ver 1.5.2 aus
Ich wollte schnell CORS
für alle Controller-Routenanfragen meines Clients aktivieren, der unter localhost:8080
ausgeführt wird. In meiner Sicherheitskonfiguration habe ich einfach einen @Bean
vom Typ FilterRegistrationBean
hinzugefügt und es funktioniert problemlos.
Hier ist der Code:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AuthConfiguration extends WebSecurityConfigurerAdapter {
....
....
@Bean
public FilterRegistrationBean corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin(corsAllowedOrigin); // @Value: http://localhost:8080
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // **permit OPTIONS call to all**
....
}
....
....
}
Sie können Spring Boot docs hier beziehen
Wenn Sie es für eine schnelle lokale Entwicklung benötigen, fügen Sie diese Anmerkung einfach auf Ihrem Controller hinzu. (Herkunft natürlich ändern)
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
Ich hatte gerade ein ähnliches Problem. Ich habe versucht, eine Anforderung von meinem Frontend in React executing on http: // localhost: 30 an mein Backend in SpringBoot auszuführen Ausführung um http: // localhost: 808 . Ich hatte zwei Fehler:
Zugriffskontrolle Ursprung zulassen
Ich habe das sehr einfach gelöst, indem ich dies meinem RestController hinzufügte:
@CrossOrigin(origins = ["http://localhost:3000"])
Nachdem ich das behoben hatte, bekam ich folgende Fehlermeldung: Der Wert des Headers 'Access-Control-Allow-Credentials' in der Antwort ist '', was 'true' sein muss
Zugriffssteuerung-Berechtigungsnachweise zulassen
Dieser kann auf zwei Arten umgangen werden:
Hinzufügen von allowCredentials = "true"
Zur CrossOrigin-Konfiguration:
@CrossOrigin(origins = ["http://localhost:3000"], allowCredentials = "true")
Ändern der Anmeldeinformationsoptionen des Abrufs in der Frontend-Anforderung. Grundsätzlich müssen Sie den Abrufaufruf wie folgt ausführen:
fetch('http://localhost:8080/your/api', { credentials: 'same-Origin' })
Hoffe das hilft =)
Sie könnten dies auch mit einem Interceptor erreichen.
Verwenden Sie die Ausnahme, um sicherzustellen, dass Sie den Lebenszyklus der Anforderung beenden:
@ResponseStatus (
value = HttpStatus.NO_CONTENT
)
public class CorsException extends RuntimeException
{
}
Setzen Sie dann in Ihrem Interceptor Header für alle OPTIONS-Anforderungen und geben Sie die Ausnahme aus:
public class CorsMiddleware extends HandlerInterceptorAdapter
{
@Override
public boolean preHandle (
HttpServletRequest request,
HttpServletResponse response,
Object handler
) throws Exception
{
if (request.getMethod().equals("OPTIONS")) {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Methods","GET, POST, PUT, OPTIONS, DELETE");
response.addHeader("Access-Control-Allow-Headers", "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,Authorization,If-Modified-Since,Cache-Control,Content-Type");
response.addHeader("Access-Control-Max-Age", "3600");
response.addHeader("charset", "utf-8");
throw new CorsException();
}
return super.preHandle(request, response, handler);
}
}
Wenden Sie den Interceptor schließlich auf alle Routen an:
@Configuration
public class MiddlewareConfig extends WebMvcConfigurerAdapter
{
@Override
public void addInterceptors (InterceptorRegistry registry)
{
registry.addInterceptor(new CorsMiddleware())
.addPathPatterns("/**");
}
}
Derzeit werden die OPTIONS-Anforderungen standardmäßig blockiert, wenn die Sicherheit aktiviert ist.
Fügen Sie einfach eine zusätzliche Bean hinzu, und Preflight-Anforderungen werden korrekt verarbeitet:
@Bean
public IgnoredRequestCustomizer optionsIgnoredRequestsCustomizer() {
return configurer -> {
List<RequestMatcher> matchers = new ArrayList<>();
matchers.add(new AntPathRequestMatcher("/**", "OPTIONS"));
configurer.requestMatchers(new OrRequestMatcher(matchers));
};
}
Bitte beachten Sie, dass dies je nach Anwendung für potenzielle Exploits möglich ist.
Eröffnete Ausgabe für eine bessere Lösung: https://github.com/spring-projects/spring-security/issues/4448