Spring CSRF覆盖安全XML配置中的"POST"注销行为

use*_*144 8 java spring csrf spring-security

目前我们的遗留应用程序的Spring CSRF解决方案存在问题,因为CSRF实现更改了默认Spring安全性Spring安全配置的行为:

<http pattern="">
...
<logout
                logout-url="/logout"
                delete-cookies="..."
                success-handler-ref="logoutSuccessHandler"
                />
<csrf/>
</http>
Run Code Online (Sandbox Code Playgroud)

org.springframework.security.config.annotation.web.configurers.LogoutConfigurer注销配置器.根据Spring文档:

添加CSRF会将LogoutFilter更新为仅使用HTTP POST.这可确保注销需要CSRF令牌,并且恶意用户无法强制注销您的用户.

进行此更改的代码如下:

 private RequestMatcher getLogoutRequestMatcher(H http) {
        if(logoutRequestMatcher != null) {
            return logoutRequestMatcher;
        }
        if(http.getConfigurer(CsrfConfigurer.class) != null) {
            this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
        } else {
            this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl);
        }
        return this.logoutRequestMatcher;
    }
Run Code Online (Sandbox Code Playgroud)

通常,对于CSRF保护,这种行为非常有意义.但对于我来说,这种实现不灵活(为什么硬编码实际的实现而不是autowire依赖?)是非常奇怪的.

问题是我们的应用程序是这样构建的,即在常规Spring注销之前,它会在Spring Controllers中执行额外的清理.主要是它实现了Switch User功能,但是以自定义方式实现.因此,更改注销链接以执行POST不是一种选择,因为主要是在自定义控制器上执行清理.

似乎为了使用指定的方法,只有一种可能的解决方案:

@RequestMapping(value = "/logout", method = RequestMethod.GET) //or it can be a post
    public String logout() {
// 1. Perform Clean up
// 2. Decide whether to logout or redirect to other page
// 3. Perform redirect based on decision
}
Run Code Online (Sandbox Code Playgroud)

//如果决定退出,则会转到此Controller方法:

  @RequestMapping(value = "csrflogout", method = RequestMethod.GET)
    public void csrfLogout(){
//1 Create manual post request
//2. Copy session information
//3. Perform Post to logout URL that is specified in security xml
     }
Run Code Online (Sandbox Code Playgroud)

从代码质量的角度来看,这种方法通常并不好.所以,有两个问题:

  1. 在Spring中进行如此严格的实现的原因是什么,并且没有提供覆盖它的任何可见的可能性(特别是我提供了代码示例如何创建它)?
  2. 修复上述问题的任何好方法.

M. *_*num 8

您描述的行为是行为,如果您没有显式配置注销支持但只启用它,您明确配置它将使用该配置.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
Run Code Online (Sandbox Code Playgroud)

这也被记录在参考指南中.

然而,真正的解决方案是你不应该使用控制器来实现额外的注销功能,而是使用LogoutHandler.这将很好地与Spring Security集成,您不需要重定向/转发到不同的URL.