加载swagger-ui.html页面时,会向host:port/和host:port/csfr发出请求。

15

我有一个Spring Boot 2应用程序(rest API),使用了Springfox Swagger 2库,包括UI库。当我打开Swagger接口 http://localhost:8080/swagger-ui.html 时,一切都按预期工作,但是会发起两个请求,logger返回404结果:

http://localhost:8080/ (我的应用程序没有映射到根目录)
http://localhost:8080/csfr (这个映射也不存在,但我知道它代表“跨站点伪造请求”)

显然Swagger这样做是因为它支持某种类型的csfr令牌检查,就像这里解释的那样。几个月来一直在进行调查,以确定是否可以配置这些404调用,因此现在正在考虑实施端点。我找不到有关要实际实现什么的信息。Swagger期望哪种头部/令牌,以及它将如何处理其中的信息?我能否使用这个使我的应用程序(或Swagger端点)更安全或可访问?简而言之:这有什么意义?


你能分享一下两个API的源代码吗?它们都返回404错误。 - Naveen
你能看到Swagger-UI和API吗?请分享相关的代码。 - Romil Patel
我认为,也许你的意思是“..向host:port/csrf发出了请求”,而不是csfr :) - chrisinmtown
2个回答

16

让我一个一个回答你的问题。

为什么会向 http://localhost:8080/http://localhost:8080/csrf 发出请求?

这是因为,Springfox Swagger 默认启用了 CSRF 支持。这意味着,当您尝试访问应用程序中的任何 Swagger 端点时,它会按照以下顺序检查 CSRF 标记,并将其附加到请求头中。

  • 位于 / 的 meta 标签中的 CSRF token
  • 端点 /csrf
  • 位于 cookie 中的 CSRF token

Springfox Swagger 附加 CSRF 标记的原因是,在您的应用程序启用了 CSRF 保护的情况下,如果 Swagger 的请求头中没有 CSRF 标记,则访问 Swagger 端点的请求将失败。

Swagger 预期哪种类型的标头/令牌,并会对其中的信息进行什么操作?

正如我之前所说,Swagger 预期一个 CSRF token,并在您尝试访问任何 Swagger 端点时将其附加到请求头中。

我可以使用此功能使我的应用程序(或 Swagger 端点)更安全或更易访问吗?

在您的应用程序中启用 CSRF 保护 可以使应用程序免受 CSRF 攻击,并不仅仅是通过提供 CSRF token 给 Swagger 附加到请求头中。如果您已经在应用程序中启用了 CSRF 保护,则必须通过上述任一方法之一提供 CSRF token 才能访问应用程序中的任何 Swagger 端点。您可以在此处阅读有关启用 CSRF 保护的用法。

我找不到实际实现的信息

如果您尚未在应用程序中启用 CSRF 保护,那么实现 Swagger 的 CSRF token 提供就没有任何用处,因为它将是多余的。但是,如果您想要实现 Swagger 的 CSRF token 提供,则可以使用以下三种方法之一:

1) 位于 / 的 meta 标签中的 CSRF token

<html>
<head>
  <meta name="_csrf" content="${_csrf.token}"/>
  <!-- default header name is X-CSRF-TOKEN -->
  <meta name="_csrf_header" content="${_csrf.headerName}"/>
</head>

假设您正在使用JSP、Thymeleaf等模板机制,此时需要进行以下操作:

2)端点/csrf

定义端点/csrf以提供CSRF令牌。

  @RequestMapping("/csrf")
  public CsrfToken csrf() {
    //logic to return the CSRF token
  }

3) 在您的cookie中使用CSRF令牌

默认搜索的cookie名称是XSRF-TOKEN,默认返回的标头名称是X-XSRF-TOKEN。Spring Security提供了一种在cookie中存储CSRF令牌的方法,符合swagger的要求,使用以下配置即可。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

实施以上三种方法之一将为Swagger提供CSRF token以附加到请求头中。

上述内容参考自GitHub PR,该PR为Springfox Swagger提供了CSRF支持,并且我之前链接的Spring Security文档也有相应说明。

目前存在一个关于默认启用CSRF支持的问题here,同时还有几个修复的开放性PR#2639#2706


你说:“这是因为Springfox Swagger默认启用了CSRF支持。” 有没有办法禁用此支持,以便不再发出请求,从而不再出现404错误? - user1884155
1
@user1884155,目前还没有办法禁用CSRF支持。我已在我的回答中添加了相关问题和开放的PR。 - Madhu Bhat
@MadhuBhat 但是如果CSRF值通过索引或/csrf暴露出来,那么它不会再次开放攻击漏洞吗? - Vuk Djapic
@VukDjapic 不知怎么的,我错过了回复你的问题。在生产级应用程序中,它可以位于 API 网关后面,这样就不会被外部暴露,因此也不会收到任何外部流量。 - Madhu Bhat

2

根据2)端点/csrf

在我的情况下,我一直禁用WebSecurity,并且对/csrf收到404错误代码。我通过一个简单的控制器来解决这个问题,如上所述。这是我的控制器:

@Controller
public class CSRFController {
    @RequestMapping(value = "/csrf", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    public ResponseEntity<CsrfToken> getToken(final HttpServletRequest request) {
        return ResponseEntity.ok().body(new HttpSessionCsrfTokenRepository().generateToken(request));
    }

如果您使用它,需要添加用于Web安全的Maven依赖项:

}

<dependency>
         <groupId>org.springframework.security</groupId>
         <artifactId>spring-security-web</artifactId>
 </dependency>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接