当网关服务器受csrf保护且请求内容类型为application/x-www-form-urlencoded时,spring网关服务器失败

vd2z7a6w  于 2021-07-13  发布在  Java
关注(0)|答案(0)|浏览(322)

当网关服务器受csrf保护且请求内容类型为application/x-www-form-urlencoded时,spring网关服务器无法从upsteam服务器获得响应

有两个简单的服务器。

第一个是网关服务器。

这是唯一的进口网关和安全。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

就像这样的安全配置。它们非常简单。所以我把它们写在同一个班上

@SpringBootApplication
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http.authorizeExchange().anyExchange().permitAll();
        http.csrf().csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse());
        return http.build();
    }
    /**
     * add csrf cookie response on every response
     * @return
     */
    @Bean
    public WebFilter addCsrfTokenFilter() {
        return (exchange, next) -> Mono.just(exchange)
                .flatMap(ex -> ex.<Mono<CsrfToken>>getAttribute(CsrfToken.class.getName()))
                .doOnNext(ex -> {
                })
                .then(next.filter(exchange));
    }
}

网关路由

spring:
  cloud:
    gateway:
      routes:
        - id: test
          uri: http://localhost:8888
          predicates:
            - Path=/test/**
          filters:
            - StripPrefix=1

第二个是上游服务器

它是一个简单的web服务器

@SpringBootApplication
@RestController
public class UpstreamApplication {

    @PostMapping("/test")
    public String postData(Dto dto) {
        return "post success";
    }

    public static void main(String[] args) {
        SpringApplication.run(UpstreamApplication.class, args);
    }

}

dto类有两个属性a和b

public class Dto {
    private String a;
    private String b;

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }
}

我在8888端口配置服务器

server:
  port: 8888

然后,我用 Postman 来测试他们。第一次,我没有csrf值。

curl --location --request POST 'http://localhost:8080/test/test' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'a=1' \
--data-urlencode 'b=2'

服务器响应无效csrf令牌异常。然后我从cookie值中得到csrf令牌值。然后我用csrf头发送请求。

curl --location --request POST 'http://localhost:8080/test/test' \
--header 'X-XSRF-TOKEN: f8db31f3-8be6-4103-8e15-5ef4594a08f0' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: XSRF-TOKEN=f8db31f3-8be6-4103-8e15-5ef4594a08f0' \
--data-urlencode 'a=1' \
--data-urlencode 'b=2'

客户端等待响应超过3分钟,但未完成。
我测试的其他内容类型,他们完成正常。
如果上游服务器的函数params为空或客户端请求params为空。它可以完成。
测试项目在这里https://github.com/ldwqh0/spring_gateway_csrf_bug

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题