【问题标题】:Spring Security: enable / disable CSRF by client type (browser / non-browser )Spring Security:通过客户端类型(浏览器/非浏览器)启用/禁用 CSRF
【发布时间】:2014-11-28 13:41:42
【问题描述】:

Spring Security 文档says

"什么时候使用CSRF保护?我们推荐使用CSRF 保护可以由浏览器处理的任何请求 普通用户。如果您只创建一个由 非浏览器客户端,您可能希望禁用 CSRF 保护。”


如果我的服务将被“浏览器”和“非浏览器”客户端(例如第三方外部服务)使用,Spring Security 是否提供了一种专门为某些类型的客户端禁用 CSRF 的方法?

【问题讨论】:

  • 我只会在浏览器页面中放一个flash程序,假设我是一个非浏览器客户端,并在用户没有CSRF保护的情况下攻击他们。
  • @NeilMcGuigan 我只为受信任的客户端禁用 CSRF,我通过 X509 和 SSL/TLS 建立信任。

标签: java spring spring-mvc spring-security csrf


【解决方案1】:

我确信在 Spring Security XML 中有一种方法可以做到这一点,但是由于我使用的是 Java Config,所以这是我的解决方案。

 @Configuration
 @EnableWebSecurity
 public class SecurityConfig {

    @Configuration
    @Order(1)
    public static class SoapApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/soap/**")
                .csrf().disable()
                .httpBasic();
        }
    }


    @Configuration
    public static class WebApiConfigurationAdapter extends WebSecurityConfigurerAdapter {

        protected void configure(HttpSecurity http) throws Exception {
            http        
                .formLogin()
                    .loginProcessingUrl("/authentication")
                    .usernameParameter("j_username")
                    .passwordParameter("j_password").permitAll()
                    .and()
                .csrf().disable()

        }
     }
}

【讨论】:

  • 你不是为所有请求禁用 csrf 吗?
  • 一旦我为一个 url 禁用 csrf,它就会为所有 url 禁用
  • @amit 是的,上面的示例为所有请求禁用 csrf,但您可以有选择地从配置中删除显式 csrf().disable()。我的示例是演示为soap(通常具有非浏览器客户端)和rest(通常为浏览器客户端提供服务)启用/禁用csrf。
  • 您的用例更细粒度,您希望在请求级别启用/禁用 csrf。我认为如果你通过 spring 官方文档,spring 会允许使用 .antMatcher 。如果您发现了什么,请告诉我们。否则我会在周末做一些研究,让你知道。
  • 我也在考虑浏览器和非浏览器用例。例如,我希望所有对 /webpages/browser csrf 的请求都启用,而其他所有 csrf 都禁用。我们可以从你的例子中实现它吗?我试过了,但是要么对所有人禁用 csrf,要么对所有人启用 csrf。如果我取得任何进展,肯定会分享...
【解决方案2】:

恕我直言,没有这样的开箱即用。在你的情况下,我会做的是有一个 URL 的层次结构,例如植根于/api,这将免除 csrf。它很容易配置。在 XML 配置中,您有一个普通的 <http> 块,包括 <csrf/>,您只需复制它并像这样修改第一个块

<http pattern="/api/**">
    ...
    <!-- csrf -->
</http>

因为它是第一个,它会被任何对/api hierachy 的请求触发,而不使用csrf,所有其他请求都会使用它。

在应用程序的正常部分,您从不使用/api/** url,并将它们保留给非浏览器使用。

然后在您的控制器中,将它们映射到它们的正常 url 和 /api 下的副本:

@Controller
@RequestMapping({ "/rootcontrollerurl", "/api/rootcontrollerurl"})
class XController {
    @RequestMapping(value = "/request_part_url", ...)
    public ModelAndView method() {
        ...
    }
}

(当然,rootcontrollerurlrequest_part_url 可能是空白的……)

但是必须分析允许非 csrf 控制请求的安全隐患,并最终从/api 层次结构中排除控制器。

【讨论】:

    【解决方案3】:

    这是我用来在特定端点上禁用 CSRF 保护的方法 在您的 appconfig-security.xml 中添加一个包含您的模式信息的节点,如下例所示:

    <http security="none" pattern="/sku/*"/>
    <http security="none" pattern="/sku/*/*"/>
    <http security="none" pattern="/sku"/>
    

    请记住,如果您要使用映射所有使用符号“*”的请求,则顺序很重要。

    【讨论】:

      猜你喜欢
      • 2021-04-23
      • 2016-05-08
      • 2019-06-28
      • 2016-04-10
      • 2016-05-06
      • 1970-01-01
      • 2014-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多