Reputation: 327
The idea is to replicate http://blog.netgloo.com/2014/09/28/spring-boot-enable-the-csrf-check-selectively-only-for-some-requests/ in webflux.
This is where I got so far:
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {
@Bean
SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity http) {
http
.csrf().requireCsrfProtectionMatcher(
new ServerWebExchangeMatcher() {
@Override
public Mono<MatchResult> matches(ServerWebExchange serverWebExchange) {
// here check if the url should have csrf or not and then return MatchResult.match() or notMatch(), however I find that if I return match then I get 'Invalid CSRF Token' error.
// return MatchResult.match();
// return MatchResult.notMatch();
}
}
).and()
.anyExchange().authenticated()
.and()
.httpBasic()
.and()
.formLogin().loginPage("/login")
.and().logout()
return http.build();
}
}
Upvotes: 3
Views: 6501
Reputation: 1
I think you are just removing all security protocol from these post/put endpoints (likely change the data). Better off having CSRF disabled and still benefiting from Spring authentication chain. Just hitting these with a permit all removes any need for a user to even be logged int. Not a good answer.
Upvotes: 0
Reputation: 148
I am too late but after a lot of research, I got a nice solution.
Let assume you want to disable CSRF check on a specific URL. In my case, I want to disable CSRF check on URLs matching this pattern /token/**
.
So, first, you need to create a NegatedServerWebExchangeMatcher
instance in which you will add all URLs pattern for which you want to disable CSRF check. In my case, I will create a method that returns NegatedServerWebExchangeMatcher
only for the /token/**
pattern.
So, here is my method.
public NegatedServerWebExchangeMatcher getURLsForDisabledCSRF() {
return new NegatedServerWebExchangeMatcher(exchange -> ServerWebExchangeMatchers.pathMatchers(ALLOWED_PATHS).matches(exchange));
}
Now delegate getURLsForDisabledCSRF()
in your requireCsrfProtectionMatcher
method like below:
http
.csrf().requireCsrfProtectionMatcher(getURLsForDisabledCSRF())
Here is my Security Config Class for my Spring Cloud API Gateway which is actually using web flux.
package com.ubaid.ms.gatewayserver.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.util.matcher.NegatedServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
/**
* <pre>
* 1. Configure
* a. Authorize only authenticated requests except {@link SecurityConfig#ALLOWED_PATHS}
* b. OAuth 2.0 Resource Server support
* 2. Disable CSRF on {@link SecurityConfig#ALLOWED_PATHS}
* </pre>
*
* @author ubaid
*/
@Configuration
@EnableWebFluxSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfig {
private final static String[] ALLOWED_PATHS = {"/token/**"};
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.csrf().requireCsrfProtectionMatcher(getURLsForDisabledCSRF())
.and()
.authorizeExchange()
.pathMatchers(ALLOWED_PATHS).permitAll()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.anyExchange()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
public NegatedServerWebExchangeMatcher getURLsForDisabledCSRF() {
return new NegatedServerWebExchangeMatcher(exchange -> ServerWebExchangeMatchers.pathMatchers(ALLOWED_PATHS).matches(exchange));
}
}
Note: Spring Cloud Version: 2020.0.2
Upvotes: 4
Reputation: 4287
config allowedOrigins:
@Bean
public WebFluxConfigurer corsConfigurer() {
return new WebFluxConfigurerComposite() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins("/goodss")
.allowedMethods("*");
}
};
}
Upvotes: -4
Reputation: 1401
This should do it
@Bean
SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity http) {
http
.csrf().requireCsrfProtectionMatcher(
new ServerWebExchangeMatcher() {
@Override
public Mono<MatchResult> matches(ServerWebExchange serverWebExchange) {
ServerWebExchangeMatchers.pathMatchers("/urls-with-csrf-check/**").matches(serverWebExchange)
}
}
).and()
.anyExchange().authenticated()
.and()
.httpBasic()
.and()
.formLogin().loginPage("/login")
.and().logout()
return http.build();
}
Upvotes: 4