Spring Security,无状态REST服务和CSRF

18

我有一个REST服务,使用Java、Spring Boot构建,并使用Basic Access Authentication的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的方法可以让它正常工作?

谢谢

2个回答

24

回答你的第一个问题,在你所描述的情境下,你不需要CSRF保护。CSRF保护的背景是确保用户不会被欺骗执行一些不想要的操作。

例如,在纯理论上,你可能已经登录了银行的网站(因此建立了一个会话),然后去了一些不良网站。这个网站可以有一个表单,向银行的API发起POST请求。因为你在那里有一个会话,如果端点没有启用CSRF保护,则请求可能会通过。

因此,CSRF主要作为浏览器+会话攻击的保护措施。如果你使用OAuth保护等纯REST API,则我认为没有CSRF的必要。

由于你使用的是Spring Boot,你也可以使用 application.properties / application.yaml 配置文件禁用CSRF。

security.enable-csrf=false
您可以查看常用应用程序属性文档页面获取更多开箱即用的配置选项。

这些服务将从一个单独托管的React应用程序中调用,但意图是使其所做的服务调用无状态。我会更新问题。感谢您的回答。 - robjwilkins
Spring 1.5.22 应用程序属性页面(https://docs.spring.io/spring-boot/docs/1.5.22.RELEASE/reference/html/common-application-properties.html)。 - Osmund Francis
如果您正在使用浏览器,则在将凭据存储在本地或会话存储中时,需要CSRF保护。请注意,即使您没有使用cookie,仍然需要进行保护。因此,我不确定这是否是正确的答案。请参见:https://dev59.com/rmEi5IYBdhLWcg3wWLPc - Khanna111
这个答案实际上与您链接的那个答案是一致的。如上所述,无状态认证不需要CSRF。它确实容易受到XSS攻击(这是一种不同的漏洞)。基本认证唯一容易受到CSRF攻击的方式是如果浏览器会记住您的用户名和密码。由于这个问题涉及到从单独托管的SPA调用的rest API。基本认证头是通过JS代码添加到fetch调用中的,而不是在浏览器的基本认证提示框中输入(因为SPA是单独托管的,例如在CDN上,而不是作为静态资产在Spring应用程序中)。 - Serban Petrescu

2
如果您希望以更规范的方式禁用csrf技术,您可以这样调用它(如果使用Java配置):
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().fullyAuthenticated()
            .and().httpBasic();
       .and()
            .csrf()
            .disable()

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