Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring security Thymeleaf Webflux安全,未将Csrf添加到视图_Spring Security_Thymeleaf_Spring Webflux - Fatal编程技术网

Spring security Thymeleaf Webflux安全,未将Csrf添加到视图

Spring security Thymeleaf Webflux安全,未将Csrf添加到视图,spring-security,thymeleaf,spring-webflux,Spring Security,Thymeleaf,Spring Webflux,我试图将csrf标签添加到表单中,但它的工作方式似乎与mvc中的不同 所以我所做的就是添加 但是,即使存在这些注释,也不存在_csrf属性 @EnableWebFluxSecurity @EnableReactiveMethodSecurity 这是我的安全WebFilterChain: http .authorizeExchange().pathMatchers( "/landing", "/

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

所以我所做的就是添加

但是,即使存在这些注释,也不存在_csrf属性

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
这是我的安全WebFilterChain:

 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由于某种原因是空的,即使注释已经就位

登录控制器:

 @GetMapping("/login")
    public String login(Model model) {
        return "public/login";
    }
还尝试添加如下控制器建议:

@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();
    }
}

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

这是我为使其工作所做的

@GetMapping("/login")
public Mono<String> login(ServerWebExchange exchange, Model model) {
    Mono<CsrfToken> token = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
    return token.map(t -> {
        model.addAttribute("_csrf", t);
        return "login";
    });
}
@GetMapping(“/login”)
公共Mono登录(ServerWebExchange,型号){
Mono-token=exchange.getAttributeOrderFault(CsrfToken.class.getName(),Mono.empty());
返回令牌.map(t->{
model.addAttribute(“_csrf”,t);
返回“登录”;
});
}

我必须加入
thymeleaf-extras-springsecurity5
(而不是
springsecurity4
)才能让它正常工作

我找不到任何CsrfToken,这意味着@mk88的答案也没有帮助

一旦我包含了以下依赖项,它就会按照设计完美地工作:

    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        <version>3.0.4.RELEASE</version>
    </dependency>

org.thymeleaf.extras
thymeleaf-extras-springsecurity5
3.0.4.1发布
来自Thymeleaf的输出:

<form action="/members" method="POST" ><input type="hidden" name="_csrf" value="432033fd-1076-4620-9f99-d0220b6d3071"/>

最干净的解决方案是使用
@ControllerAdvice
,详细说明如下:

@ControllerAdvice
公共类安全控制器建议{
@模型属性
Mono csrfToken(服务器WebExchange){
Mono-csrfToken=exchange.getAttribute(csrfToken.class.getName());
返回csrfToken.doOnSuccess(token->exchange.getAttributes()
.put(CsrfRequestDataValueProcessor.DEFAULT_CSRF_ATTR_NAME,token));
}
}

在WebFlux中,默认情况下,CsrfToken信息似乎没有实际添加到模型中。(见附件)

解决方法是添加一个ControllerAdvice,订阅令牌信息并通过ComponentScan引用它,或者将其声明为显式bean,如下所示:

(我使用的是Kotlin,但在Java中也应该如此)

import org.springframework.security.web.reactive.result.view.CsrfRequestDataValueProcessor.DEFAULT\u CSRF\u ATTR\u NAME
导入org.springframework.security.web.server.csrf.CsrfToken
导入org.springframework.web.bind.annotation.ControllerAdvice
导入org.springframework.web.bind.annotation.ModelAttribute
导入org.springframework.web.server.ServerWebExchange
导入reactor.core.publisher.Mono
@控制器建议
类CsrfControllerAdvice{
@ModelAttribute(值=默认值\u CSRF\u属性\u名称)
趣味csrfToken(exchange:ServerWebExchange):Mono{
返回exchange.getAttributeOrderFault(CsrfToken::class.java.name,Mono.empty())
}
}

您是否收到任何错误?@SupunDharmarathne更新了问题。关于这一点,您是否知道为什么当表单的enctype为multipart时,我会收到“Invalid CSRF Token”,但在其他情况下工作正常?我有时需要上传文件,这需要使用multipart。提出了另一个问题:
@GetMapping("/login")
public Mono<String> login(ServerWebExchange exchange, Model model) {
    Mono<CsrfToken> token = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
    return token.map(t -> {
        model.addAttribute("_csrf", t);
        return "login";
    });
}
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        <version>3.0.4.RELEASE</version>
    </dependency>
<form action="/members" method="POST" ><input type="hidden" name="_csrf" value="432033fd-1076-4620-9f99-d0220b6d3071"/>
@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));
    }
}
import org.springframework.security.web.reactive.result.view.CsrfRequestDataValueProcessor.DEFAULT_CSRF_ATTR_NAME
import org.springframework.security.web.server.csrf.CsrfToken
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono

@ControllerAdvice
class CsrfControllerAdvice {

    @ModelAttribute(value = DEFAULT_CSRF_ATTR_NAME)
    fun csrfToken(exchange: ServerWebExchange): Mono<CsrfToken> {
        return exchange.getAttributeOrDefault(CsrfToken::class.java.name, Mono.empty())
    }
}