Я пытаюсь интегрировать диалект безопасности 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/]