Spring Security、无状态 REST 服务和 CSRF

2022-09-03 01:05:58

我有一个REST服务,使用Java,Spring-boot和使用Spring Security with Basic Access Authentication构建。没有视图,没有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 保护并提供标头,则弹簧 CsrfFilter 会尝试根据 .但是,由于它是无状态的REST服务,因此我没有会话,也没有“登录”。x-csrf-tokenHttpServletRequest

我有一个配置类,看起来像这样:

@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保护。有没有另一种方法可以配置弹簧安全性,以便它能够正常工作?

谢谢


答案 1

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

例如,在纯粹的理论中,您可以登录银行的网站(从而建立会话),然后转到某个阴暗的网站。此站点可以有一个表单,向银行的 API 发出 POST 请求。因为您在那里有一个会话,所以如果端点不受 CSRF 保护,则请求可能会通过。

因此,CSRF主要充当针对基于浏览器+会话的攻击的保护。如果你公开一个纯 REST API,例如 OAuth 保护,那么我看不出 CSRF 有任何理由。

使用 Spring boot 时,还可以使用 / 配置文件禁用 CSRF。application.propertiesapplication.yaml

security.enable-csrf=false

您可以查看通用应用程序属性文档页面,了解更多现成的配置选项。


答案 2

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

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