spring-security - Thymeleaf Webflux 安全性,Csrf 未添加到 View 中

标签 spring-security thymeleaf spring-webflux

我正在尝试将 csrf 标签添加到表单中,但它的工作方式似乎与 mvc 中的不同。

所以我所做的是添加<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
登录表单但是 _csrf 属性不存在,即使这些注释存在

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity

这是我的 SecurityWebFilterChain:
 http
                .authorizeExchange().pathMatchers(
                "/landing",
                "/",
                "/register",
                "/login",
                "/favicon.ico",
                "/js/**",
                "/fonts/**",
                "/assets/**",
                "/css/**",
                "/webjars/**").permitAll()
                .anyExchange().authenticated()
                .and()
                .httpBasic()
                .and()
                .formLogin().loginPage("/login")
                .and().logout()

我错过了什么?

更新:
添加了我正在使用的相关依赖项。
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version>

</properties>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
            <version>3.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.github.jpenren</groupId>
            <artifactId>thymeleaf-spring-data-dialect</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.9.RELEASE</version>
        </dependency>
    </dependencies>

更新
当我在登录表单中包含带有 csrf 的隐藏输入标签时:
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />

我收到此错误:
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "_csrf.parameterName" (template: "public/login" - line 75, col 17)

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'parameterName' cannot be found on null

因为 _csrf 出于某种原因为空,即使注释已经到位。

登录 Controller :
 @GetMapping("/login")
    public String login(Model model) {
        return "public/login";
    }

还尝试添加这样的 Controller 建议:
@ControllerAdvice
public class SecurityAdvice {

    @ModelAttribute("_csrf")
    Mono<CsrfToken> csrfToken(final ServerWebExchange exchange) {

        final Mono<CsrfToken> csrfToken = exchange.getAttribute(CsrfToken.class.getName());

        return csrfToken.doOnSuccess(token -> exchange.getAttributes()
                .put(DEFAULT_CSRF_ATTR_NAME, token)).log();
    }
}

与此处使用的类似:https://github.com/daggerok/csrf-spring-webflux-mustache

然而,这导致
java.lang.NullPointerException: null
    at com.a.Config.SecurityAdvice.csrfToken(SecurityAdvice.java:23) ~[classes/:na]

这一行是最后一个片段的返回部分。

最佳答案

适用于所有 Controller 的最干净的解决方案是使用 @ControllerAdvice如详细 in the documentation :

@ControllerAdvice
public class SecurityControllerAdvice {
    @ModelAttribute
    Mono<CsrfToken> csrfToken(ServerWebExchange exchange) {
        Mono<CsrfToken> csrfToken = exchange.getAttribute(CsrfToken.class.getName());
        return csrfToken.doOnSuccess(token -> exchange.getAttributes()
                .put(CsrfRequestDataValueProcessor.DEFAULT_CSRF_ATTR_NAME, token));
    }
}

关于spring-security - Thymeleaf Webflux 安全性,Csrf 未添加到 View 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50907381/

相关文章:

xml - 安全命名空间不支持元素 [custom-filter] 的修饰

java - Spring 安全和身份验证提供程序

html - 在 thymeleaf 中创建一个表

java - WebClient - 如何获取请求正文?

grails spring 安全角色和组

java - 我可以在 GAE 上使用 Spring 吗?

java - 我在哪里可以获得有关所有 thymeleaf 开箱即用处理器的详细解释?

html - Thymeleaf 吞下数据列表中的选项标签

spring - 如何使用 Reactor (Spring WebClient) 做重复调用?

spring - 如何使 AuditorAware 与 Spring Data Mongo Reactive 一起工作