Spring 安全、无状态 REST 服务和 CSRF
Spring Security, Stateless REST service and CSRF
我有一个 REST 服务,使用 Java、Spring-boot 构建并使用 Spring 安全和基本访问身份验证。没有视图,没有 JSP 等,没有 'login',只有可以从单独托管的 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
header,那么 spring CsrfFilter 会尝试将其与来自(我认为)[=35 的值进行交叉检查=] HttpServletRequest
中的 cookie。但是,由于它是无状态 REST 服务,我没有 session,也没有 'logged in'。
我的配置 class 如下所示:
@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 安全性以使其起作用?
谢谢
回答你的第一个问题,在你描述的上下文中,你不需要 CSRF 保护。 CSRF 保护的背景是确保用户不被诱骗去做一些不受欢迎的行为。
例如,在纯理论中,您可能已经登录到一家银行的网站(并因此建立了一个会话),然后去了一些可疑的网站。该网站可以有一个表格,向银行的 API 提出 POST 请求。因为你在那里有一个会话,如果端点不受 CSRF 保护,那么请求可能会通过。
因此,CSRF 主要用于防止基于浏览器+会话的攻击。如果您使用例如公开纯 REST API OAuth 保护,那么我看不出任何 CSRF 的理由。
当您使用 spring 引导时,您还可以使用 application.properties
/ application.yaml
配置文件禁用 CSRF。
security.enable-csrf=false
您可以查看 Common Application Properties 文档页面以了解更多 out-of-the-box 配置选项。
如果你想以更合适的方式禁用 csrf,你可以这样调用它(如果使用 java 配置)
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and().httpBasic();
.and()
.csrf()
.disable()
我有一个 REST 服务,使用 Java、Spring-boot 构建并使用 Spring 安全和基本访问身份验证。没有视图,没有 JSP 等,没有 'login',只有可以从单独托管的 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
header,那么 spring CsrfFilter 会尝试将其与来自(我认为)[=35 的值进行交叉检查=] HttpServletRequest
中的 cookie。但是,由于它是无状态 REST 服务,我没有 session,也没有 'logged in'。
我的配置 class 如下所示:
@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 安全性以使其起作用?
谢谢
回答你的第一个问题,在你描述的上下文中,你不需要 CSRF 保护。 CSRF 保护的背景是确保用户不被诱骗去做一些不受欢迎的行为。
例如,在纯理论中,您可能已经登录到一家银行的网站(并因此建立了一个会话),然后去了一些可疑的网站。该网站可以有一个表格,向银行的 API 提出 POST 请求。因为你在那里有一个会话,如果端点不受 CSRF 保护,那么请求可能会通过。
因此,CSRF 主要用于防止基于浏览器+会话的攻击。如果您使用例如公开纯 REST API OAuth 保护,那么我看不出任何 CSRF 的理由。
当您使用 spring 引导时,您还可以使用 application.properties
/ application.yaml
配置文件禁用 CSRF。
security.enable-csrf=false
您可以查看 Common Application Properties 文档页面以了解更多 out-of-the-box 配置选项。
如果你想以更合适的方式禁用 csrf,你可以这样调用它(如果使用 java 配置)
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and().httpBasic();
.and()
.csrf()
.disable()