【问题标题】:Spring Security, Stateless REST service and CSRFSpring Security、无状态 REST 服务和 CSRF
【发布时间】:2018-08-05 17:16:42
【问题描述】:

我有一个 REST 服务,使用 Java、Spring-boot 构建,并使用带有基本访问身份验证的 Spring Security。没有视图,没有 JSP 等,没有“登录”,只有可以从单独托管的 React 应用程序调用的无状态服务。

我已经阅读了各种有关 CSRF 保护的文档,但无法决定我应该使用 spring-security CSRF 配置,还是仅仅禁用它?如果我禁用 csrf 保护,我可以使用 curl 使用我的基本身份验证调用服务,如下所示:

curl -H "authorization:Basic c35sdfsdfjpzYzB0dDFzaHA=" -H "content-type:application/json" -d '{"username":"user","password":"password","roles":"USER"}' localhost:8081/api/v1/user

如果我启用 csrf 保护并提供 x-csrf-token 标头,则 spring CsrfFilter 会尝试将其与来自(我认为)HttpServletRequest 中的会话 cookie 的值进行交叉检查。但是,由于它是无状态的 REST 服务,因此我没有会话,也没有“登录”。

我有一个如下所示的配置类:

@EnableWebSecurity
@Configuration
public class ServiceSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().fullyAuthenticated()
                .and().httpBasic();
        if (!serviceProperties.isCsrfEnabled()) {
            http.csrf().disable();
        }
    }

我想得越多,似乎我就越需要禁用 CSRF 保护。是否有另一种方法来配置 Spring Security 以使其正常工作?

谢谢

【问题讨论】:

    标签: java rest spring-boot spring-security csrf


    【解决方案1】:

    要回答您的第一个问题,在您描述的上下文中,您不需要 CSRF 保护。 CSRF 保护的背景是确保用户不会被诱骗做一些不需要的动作。

    例如,从理论上讲,您可能已经登录了银行的网站(并因此建立了一个会话),然后又去了一些不正当的网站。该站点可能有一个向银行 API 发出 POST 请求的表单。因为你在那里有一个会话,如果端点不受 CSRF 保护,那么请求可能会通过。

    因此,CSRF 主要用作针对基于浏览器 + 会话的攻击的保护。如果您使用例如公开一个纯 REST API OAuth 保护,那么我看不出 CSRF 的任何原因。

    当您使用 Spring Boot 时,您还可以使用 application.properties / application.yaml 配置文件禁用 CSRF。

    security.enable-csrf=false
    

    您可以查看Common Application Properties 文档页面,了解更多开箱即用的配置选项。

    【讨论】:

    • 服务将从单独托管的 React 应用程序中调用,但其目的是使服务调用成为无状态的。我会更新问题。谢谢你的回答
    • Spring 1.5.22 应用程序属性页面 (docs.spring.io/spring-boot/docs/1.5.22.RELEASE/reference/html/…)。
    • 如果您使用的是浏览器,那么当您将凭据存储在浏览器的本地或会话存储中时,您需要 CSRF 保护。请注意,您没有使用 cookie,但仍然使用。所以我不确定这是一个正确的答案。见:stackoverflow.com/questions/21357182/…
    • 这个答案实际上与您链接的答案一致。如那里所述,无状态身份验证不需要 CSRF。它确实容易受到 XSS 的攻击(这是一个不同的漏洞)。基本身份验证易受 CSRF 攻击的唯一方法是浏览器是否会记住您的用户名和密码。因为这个问题是关于一个休息 API,从一个单独的 SPA 调用。基本身份验证标头通过 JS 代码添加到 fetch 调用中,而不是在浏览器的基本身份验证提示中输入(因为 SPA 是单独托管的,例如在 CDN 上而不是在 Spring 应用程序中作为静态资产)。
    【解决方案2】:

    如果你想以更正确的方式禁用 csrf,你可以这样调用它(如果使用 java 配置)

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().fullyAuthenticated()
                .and().httpBasic();
           .and()
                .csrf()
                .disable()
    

    【讨论】:

      猜你喜欢
      • 2017-04-05
      • 2015-09-18
      • 2014-03-18
      • 2015-12-10
      • 2021-01-16
      • 2020-09-06
      • 2014-01-04
      • 2013-03-21
      • 2018-03-05
      相关资源
      最近更新 更多