Spring Security:激活CSRF保护会破坏其他功能

问题描述

我正在使用Spring Security 5.0.13,我想为登录页面激活csrf保护。我使用的是xml配置,我将其更改为

<http>
    ...
    <csrf disabled="true"/>
</http>

<bean id="csrfMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
    <constructor-arg name="pattern" value="/j_spring_security_check"/>
    <constructor-arg name="httpMethod" value="POST"/>
</bean>
<csrf request-matcher-ref="csrfMatcher" />

然而,j_spring_security_logout端点现在期望一个POST请求,而它过去接受一个GET请求。我知道最好有一个POST请求注销按钮,但是我不能破坏此功能,因为它已在我的控制范围之外的其他地方使用。

如何在不影响注销url动词的情况下为登录页面激活csrf保护?

解决方法

CSRF保护要求您为所有引起更改的请求发送包含CRSF属性值的隐藏输入。这就是保护您的原因-该CSRF属性是由服务器生成的,因此无法通过从网站以外的其他位置发送请求来伪造。

您只能在带有post请求的表单内发送隐藏的输入,因此,如果要使用csrf,则需要使用post。好消息是-这很容易,大多数模板引擎都会自动为您设置所有内容。

使用Thymeleaf,您甚至不需要更改任何内容,它就会在您的帖子请求中自动生成此属性。

使用小胡子,您需要添加以下属性:

spring.mustache.expose-request-attributes=true

然后使用以下格式:

<form id="logoutForm" method="POST" action="/logout">
    <input type="hidden" name="_csrf" value="{{_csrf.token}}"/>
    <button type=submit>Logout</button>
</form>

如您所见,这确实相对容易,但是您必须将隐藏的crsf.token值添加到每个帖子请求,实现(取决于模板引擎),就像我对thymeleaf所说的那样,您不必担心它。

,

根据Spring Security reference docs,您可以修改Spring Security与/logout端点的匹配方式。默认情况下,它查找POST /logout,但是您可以将其配置为查找GET /logout

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) {
        http
            // ... other configs
            .logout(logout -> logout
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout","GET"))
            );
    }
}

尽管可以声明自己的LogoutFilterregister it类型的<logout>,但<bean>元素没有直接的XML等效项。或选择logging a ticket将其添加到<logout>