解析模板时出错 [注册/保存],模板可能不存在或可能无法被任何已配置的模板解析器 _csft 访问

Posted

技术标签:

【中文标题】解析模板时出错 [注册/保存],模板可能不存在或可能无法被任何已配置的模板解析器 _csft 访问【英文标题】:Error resolving template [register/save], template might not exist or might not be accessible by any of the configured Template Resolvers _csft 【发布时间】:2022-01-19 05:35:43 【问题描述】:

我有这个错误:

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Wed Dec 15 22:36:23 EST 2021
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [register/save], template might not exist or might not be accessible by any of the configured Template Resolvers
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [register/save], template might not exist or might not be accessible by any of the configured Template Resolvers
    at org.thymeleaf.engine.TemplateManager.resolveTemplate(TemplateManager.java:869)
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:607)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362)
    at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter.doFilterInternal(DefaultLogoutPageGeneratingFilter.java:52)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:216)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:141)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:833)

当尝试从带有 csft 保护输入字段的 register.html 页面的重定向访问此资源时:

            <form autocomplete="off" th:action="@/register/save" th:object="$userAccount" method="post" class="form-signin" role="form">
                <h3 class="form-signin-heading">Registration Form</h3>
                <div class="form-group">
                    <div class="">
                        <input type="text" th:field="*userName" placeholder="User Name" class="form-control" />
                    </div>
                </div>
                <div class="form-group">
                    <div class="">
                        <input type="text" th:field="*email" placeholder="Email" class="form-control" />
                    </div>
                </div>
                <div class="form-group">
                    <div class="">
                        <input type="password" th:field="*password" placeholder="Password" class="form-control" />
                    </div>
                </div>
                
                <input type="hidden" name="_csrf" th:value="$_csrf.token" />
                
                <div class="form-group">
                    <div class="">
                        <button type="submit" class="btn btn-primary btn-block">Register User</button>
                    </div>
                </div>
                <!-- <span th:utext="$successMessage"></span> -->
            </form>

/register/save 资源和 html 的资源在 SecurityController.java 中定义如下:

@Controller
public class SecurityController 
    
    @Autowired
    UserAccountRepository accountRepo;
    
    @Autowired
    BCryptPasswordEncoder bCryptEncoder;
    
    @GetMapping("/register")
    public String register(Model model) 
        UserAccount userAccount = new UserAccount();
        model.addAttribute("userAccount", userAccount);
        
        return "security/register";
    
    
    @PostMapping("/register/save")
    public String saveUser(Model model, UserAccount user) 
        user.setPassword(bCryptEncoder.encode(user.getPassword()));
        accountRepo.save(user);
        return "redirect:/";
    


安全配置是这样定义访问的,允许通过/** permitAll访问注册/保存:

    @Override
    protected void configure(HttpSecurity http) throws Exception
        http.authorizeRequests()
            .antMatchers("/users/new").hasRole("ADMIN")
            .antMatchers("/groups/new").hasRole("ADMIN")
            .antMatchers("/", "/**").permitAll()
            .and()
            .formLogin();
    

似乎该错误是控制器名称(@PostMapping(“/register/save”))和register.html(th:action =“@/register/save”的简单匹配错误) 调用它。但我让一切都同意。可能我需要一个记录或设置一个我到目前为止没有使用过的 TemplateResolver。我需要验证什么?

非常感谢。

【问题讨论】:

您确定您没有从控制器返回register/save 作为返回值吗?因为显示的错误是 Thymeleaf 在类路径上搜索 register/save.html 并没有找到它。 在 SecurityController 类中更改为 register/user/ 而不是 /register/save。结果相同。 我的意思是@GetMapping注解方法中的返回值。您在那里有return "security/register";,但来自Thymeleaf 的错误显示Error resolving template [register/save],这表明您在某处有一个@GetMapping 注释方法,其中有return "register/save" 你说得对@WimDeblaume。我在 rc/main/resources/templates/register/save.html 中创建了 save.html,它可以工作。谢谢。顺便说一句,我不明白为什么你需要一些 html 文件来调用控制器中的 PostMapping 方法,它已经存在于调用 html 文件中。还是谢谢。 如果您不完全了解它的工作原理,您可能需要阅读Form handling with Thymeleaf。 【参考方案1】:

看这里:https://www.yawintutor.com/error-1564-error-resolving-template/。似乎缺少与 @PostMapping("/register/save") 同名的 html 文件目标。我的意思是你需要创建一个 save.html 文件。 src/main/resources/templates/register/save.html 的种类。有了这个,您可以从 register.html 源调用文件中的 SecurityController.java 中执行 PostMapping("/register/save") 操作。

【讨论】:

以上是关于解析模板时出错 [注册/保存],模板可能不存在或可能无法被任何已配置的模板解析器 _csft 访问的主要内容,如果未能解决你的问题,请参考以下文章

解析模板 [] 时出错,模板可能不存在或可能无法被任何已配置的模板解析器访问

解析模板时出错 [/],模板可能不存在或可能无法被任何已配置的模板解析器访问

解析模板“欢迎”时出错,模板可能不存在或可能无法被任何已配置的模板解析器访问

解析模板 [registration] 时出错,模板可能不存在或可能无法被任何已配置的模板解析器访问

解析模板“home”时出错,模板可能不存在或可能无法被任何已配置的模板解析器访问

解析模板“登录”时出错,模板可能不存在或可能无法被任何已配置的模板解析器访问