Подтвердить что ты не робот

Spring Boot Security + Thymeleaf: класс IProcessorDialect отсутствует

Я пытаюсь интегрировать диалект безопасности Thymeleaf (например, sec: authorize tag) в приложение безопасности Spring Boot + Spring, которое работает правильно.

После некоторых исследований я обнаружил, что решение для активации:

Добавьте зависимость в файл POM:

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
    <version>3.0.0.RELEASE</version>
</dependency>

и включите тег в верхней части файла шаблона:

<html   xmlns:th="http://www.thymeleaf.org" lang="en"
        xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">

До сих пор так хорошо. Зависимость найдена, метки распознаются в разметке.

Однако они не учитываются и отображаются в окончательном HTML.

Из-за проблемы в автоматической конфигурации Spring Boot, которая не включается, кажется, что необходимо вручную добавить SpringSecurityDialect Bean в один класс @Configuration, чтобы включить его (несколько вопросов, найденных в StackOverflow, были решены этим):

@Bean
    public SpringSecurityDialect securityDialect() {
        return new SpringSecurityDialect();
    }

Вот что вызывает проблему: когда я добавляю этот Bean в мою конфигурацию загрузки Spring, он вызывает исключение, потому что не может найти класс org.thymeleaf.dialect.IProcessorDialect. Вот ошибка:

> java.lang.IllegalStateException: Could not evaluate condition on
> org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer
> due to org/thymeleaf/dialect/IProcessorDialect not found. Make sure
> your own configuration does not rely on that class. This can also
> happen if you are @ComponentScanning a springframework package (e.g.
> if you put a @ComponentScan in the default package by mistake)

Что мне не хватает? Это ошибка, исходящая от Тимелеафа? Spring Загрузка? Мой собственный код? Заранее благодарим за помощь!

Вот некоторые из моих файлов, связанных с моей проблемой:

Application.java

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
      public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
            @Override
            protected void postProcessContext(Context context) {
              SecurityConstraint securityConstraint = new SecurityConstraint();
              securityConstraint.setUserConstraint("CONFIDENTIAL");
              SecurityCollection collection = new SecurityCollection();
              collection.addPattern("/*");
              securityConstraint.addCollection(collection);
              context.addConstraint(securityConstraint);
            }
          };

        tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
        return tomcat;
      }

      private Connector initiateHttpConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        connector.setRedirectPort(8443);

        return connector;
      }
}

WebMvcConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    /**
     * Configure relationships between URLs and view names
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    }

    @Bean
    public SpringSecurityDialect securityDialect() {
        return new SpringSecurityDialect();
    }
}

Тимелеар:

<!DOCTYPE html>
<html   xmlns:th="http://www.thymeleaf.org" lang="en"
        xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">

....

<div sec:authorize="isAuthenticated()">
    LOGGED IN
</div>
<div sec:authorize="isAnonymous()">
    ANONYMOUS
</div>

....

Полный вывод консоли при запуске приложения:

>  :: Spring Boot ::        (v1.3.4.RELEASE)
> 
> 2016-05-17 17:22:59.951  INFO 96267 --- [  restartedMain]
> edu.rmit.eres.estored.Application        : Starting Application on
> w8031808.local with PID 96267
> (/Users/guillaume/dev/workspace/e-stored/target/classes started by
> guillaume in /Users/guillaume/dev/workspace/e-stored) 2016-05-17
> 17:22:59.956  INFO 96267 --- [  restartedMain]
> edu.rmit.eres.estored.Application        : No active profile set,
> falling back to default profiles: default 2016-05-17 17:23:00.239 
> INFO 96267 --- [  restartedMain]
> ationConfigEmbeddedWebApplicationContext : Refreshing
> org.springframework.boot[email protected]16f53cde:
> startup date [Tue May 17 17:23:00 AEST 2016]; root of context
> hierarchy 2016-05-17 17:23:01.578 ERROR 96267 --- [  restartedMain]
> o.s.boot.SpringApplication               : Application startup failed
> 
> java.lang.IllegalStateException: Could not evaluate condition on
> org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer
> due to org/thymeleaf/dialect/IProcessorDialect not found. Make sure
> your own configuration does not rely on that class. This can also
> happen if you are @ComponentScanning a springframework package (e.g.
> if you put a @ComponentScan in the default package by mistake)    at
> org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:55)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:102)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:178)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:140)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:116)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:333)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:273)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:98)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:678)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:520)
> ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at
> org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
> ~[spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]    at
> org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
> [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]     at
> org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361)
> [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]     at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
> [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]     at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:1191)
> [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]     at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:1180)
> [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]     at
> edu.rmit.eres.estored.Application.main(Application.java:24)
> [classes/:na]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
> Method) ~[na:1.8.0_60]    at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> ~[na:1.8.0_60]    at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> ~[na:1.8.0_60]    at java.lang.reflect.Method.invoke(Method.java:497)
> ~[na:1.8.0_60]    at
> org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
> [spring-boot-devtools-1.3.4.RELEASE.jar:1.3.4.RELEASE] Caused by:
> java.lang.NoClassDefFoundError:
> org/thymeleaf/dialect/IProcessorDialect   at
> java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_60]  at
> java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_60]
>   at
> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
> ~[na:1.8.0_60]    at
> java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
> ~[na:1.8.0_60]    at
> java.net.URLClassLoader.access$100(URLClassLoader.java:73)
> ~[na:1.8.0_60]    at
> java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_60]
>   at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
> ~[na:1.8.0_60]    at java.security.AccessController.doPrivileged(Native
> Method) ~[na:1.8.0_60]    at
> java.net.URLClassLoader.findClass(URLClassLoader.java:361)
> ~[na:1.8.0_60]    at
> java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_60]
>   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
> ~[na:1.8.0_60]    at
> java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_60]
>   at
> org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:151)
> ~[spring-boot-devtools-1.3.4.RELEASE.jar:1.3.4.RELEASE]   at
> java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_60]
>   at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_60]
>   at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
> ~[na:1.8.0_60]    at java.lang.Class.getDeclaredMethods(Class.java:1975)
> ~[na:1.8.0_60]    at
> org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:612)
> ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at
> org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:524)
> ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at
> org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:510)
> ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at
> org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:570)
> ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:683)
> ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:627)
> ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:597)
> ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at
> org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1445)
> ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at
> org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:975)
> ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at
> org.springframework.boot.autoconfigure.condition.BeanTypeRegistry$OptimizedBeanTypeRegistry.addBeanTypeForNonAliasDefinition(BeanTypeRegistry.java:289)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.boot.autoconfigure.condition.BeanTypeRegistry$OptimizedBeanTypeRegistry.addBeanType(BeanTypeRegistry.java:278)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.boot.autoconfigure.condition.BeanTypeRegistry$OptimizedBeanTypeRegistry.getNamesForType(BeanTypeRegistry.java:259)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:182)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:171)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:139)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:113)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  at
> org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
> ~[spring-boot-autoconfigure-1.3.4.RELEASE.jar:1.3.4.RELEASE]  ... 22
> common frames omitted Caused by: java.lang.ClassNotFoundException:
> org.thymeleaf.dialect.IProcessorDialect   at
> java.net.URLClassLoader.findClass(URLClassLoader.java:381)
> ~[na:1.8.0_60]    at
> java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_60]
>   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
> ~[na:1.8.0_60]    at
> java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_60]
>   ... 56 common frames omitted
> 
> 2016-05-17 17:23:01.581  INFO 96267 --- [  restartedMain]
> .b.l.ClasspathLoggingApplicationListener : Application failed to start
> with classpath:
> [file:/Users/guillaume/dev/workspace/e-stored/target/classes/]
4b9b3361

Ответ 1

Спасибо за M. Deinum полезный комментарий!

Похоже, что "Thymeleaf Extras для Spring Security 4" версии 3.0.0 еще не поддерживается.

Я изменил версию зависимости Maven от Thymeleaf thymeleaf-extras-springsecurity4 в моем файле POM с 3.0.0 до последней версии 2.xx(2.1.2 на момент публикации), и она исправила проблему.

От:

    <!-- http://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity4 -->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>3.0.0.RELEASE</version>
    </dependency>

в

    <!-- http://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity4 -->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>2.1.2.RELEASE</version>
    </dependency>

Проблема больше не появляется, веб-приложение запускается правильно, и теги распознаются:)

Ответ 2

Наконец, он работает со стандартными конфигурациями загрузки spring следующим образом  - spring загрузочная версия 1.5.8.RELEASE

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
         <groupId>org.thymeleaf.extras</groupId>
         <artifactId>thymeleaf-extras-springsecurity4</artifactId>
    </dependency>

Это добавит

  • Thymeleaf-spring4 version 2.1.5.RELEASE
  • Thymeleaf vesrsion 2.1.5.RELEASE
  • Версия Thymeleaf-extra-springsecurity4 2.1.3.RELEASE
  • Spring -security 4.2.3.RELEASE

    Обязательно игнорируйте определение bean SpringSecurityDialect в файле конфигурации, это не сработает. просто используйте значение по умолчанию, если вам не нужно делать другие вещи.

Ответ 3

Это спасает мою жизнь.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Использование: Maven 3.5.0
Java 1.8.0_152
Spring: https://start.spring.io → Spring Boot:: (v2.0.0.BUILD-SNAPSHOT)