Spring Webflux在特定URL上禁用CSRF

Spring Webflux在特定URL上禁用CSRF,spring,spring-security,spring-webflux,Spring,Spring Security,Spring Webflux,这个想法是在webflux中复制 这就是我到目前为止所得到的: @Configuration @EnableWebFluxSecurity @EnableReactiveMethodSecurity public class SecurityConfig { @Bean SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity http) { http

这个想法是在webflux中复制

这就是我到目前为止所得到的:

@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();
    }
}
@配置
@启用WebFluxSecurity
@EnableReactiveMethodSecurity
公共类SecurityConfig{
@豆子
SecurityWebFilterChain springSecurityFilterChain(最终服务器HttpSecurity http){
http
.csrf().requireCsrfProtectionMatcher(
新服务器WebExchangeMatcher(){
@凌驾
公共Mono匹配(ServerWebExchange ServerWebExchange){
//在这里检查url是否应该有csrf,然后返回MatchResult.match()或notMatch(),但是我发现如果返回match,则会出现“无效csrf令牌”错误。
//返回MatchResult.match();
//返回MatchResult.notMatch();
}
}
).及()
.anyExchange().authenticated()
.及()
.httpBasic()
.及()
.formLogin().login页面(“/login”)
。和()。注销()
返回http.build();
}
}
这应该可以

    @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();
    }
@Bean
SecurityWebFilterChain springSecurityFilterChain(最终服务器HttpSecurity http){
http
.csrf().requireCsrfProtectionMatcher(
新服务器WebExchangeMatcher(){
@凌驾
公共Mono匹配(ServerWebExchange ServerWebExchange){
ServerWebExchangeMatchers.pathMatchers(“/URL带csrf check/**”).matches(serverWebExchange)
}
}
).及()
.anyExchange().authenticated()
.及()
.httpBasic()
.及()
.formLogin().login页面(“/login”)
。和()。注销()
返回http.build();
}
配置允许的来源:

@Bean
public WebFluxConfigurer corsConfigurer() {
    return new WebFluxConfigurerComposite() {

        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry
                .addMapping("/**")
                .allowedOrigins("/goodss")
                .allowedMethods("*");
        }
    };
}

我太晚了,但经过大量研究,我找到了一个很好的解决方案

假设您想禁用特定URL上的CSRF检查。在我的例子中,我想对匹配此模式的URL禁用CSRF检查
/token/**

因此,首先,您需要创建一个
NegatedServerWebExchangeMatcher
实例,在该实例中,您将添加要禁用CSRF检查的所有URL模式。在本例中,我将创建一个方法,该方法仅针对
/token/**
模式返回
否定服务器WebExchangeMatcher
。 这是我的方法

    public NegatedServerWebExchangeMatcher getURLsForDisabledCSRF() {
        return new NegatedServerWebExchangeMatcher(exchange -> ServerWebExchangeMatchers.pathMatchers(ALLOWED_PATHS).matches(exchange));
    }
现在,在
requireCsrfProtectionMatcher
方法中委托
getURLsForDisabledCSRF()
,如下所示:

        http
                .csrf().requireCsrfProtectionMatcher(getURLsForDisabledCSRF())
这是我的SpringCloudAPI网关的安全配置类,它实际上使用WebFlux

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

package com.ubaid.ms.gatewayserver.config;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.http.HttpMethod;
导入org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
导入org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
导入org.springframework.security.config.web.server.ServerHttpSecurity;
导入org.springframework.security.web.server.SecurityWebFilterChain;
导入org.springframework.security.web.server.util.matcher.NegatedServerWebExchangeMatcher;
导入org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
/**
* 
* 1. 配置
*a。仅授权经过身份验证的请求,除了{@link SecurityConfig#ALLOWED_path}
*b。OAuth 2.0资源服务器支持
* 2. 在{@link SecurityConfig#ALLOWED_path}上禁用CSRF
* 
*
*@author-ubaid
*/
@配置
@启用WebFluxSecurity
@EnableGlobalMethodSecurity(jsr250Enabled=true)
公共类SecurityConfig{
私有最终静态字符串[]允许的_路径={“/token/**”};
@豆子
公共安全WebFilterChain安全WebFilterChain(ServerHttpSecurity http){
http
.csrf().requireCsrfProtectionMatcher(getURLsForDisabledCSRF())
.及()
.授权交易所()
.pathMatchers(允许的路径).permitAll()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.anyExchange()
.authenticated()
.及()
.oauth2ResourceServer()
.jwt();
返回http.build();
}
public-negativeServerWebExchangeMatcher getURLsForDisabledCSRF(){
返回新的否定ServerWebExchangeMatcher(exchange->ServerWebExchangeMatchers.pathMatchers(允许的路径).matches(exchange));
}
}

注意:Spring云版本:2020.0.2

这是CORS,不是CSRF。