Spring 4,Thymeleaf,安全性:未找到WebApplicationContext:未注册ContextLoaderListener
它让我发疯。。。所有的事情都很顺利,我不得不痛苦地从更多不太好的例子中寻找,现在我被一些本该开箱即用的东西困住了 重要提示:我使用Java配置,因此根本没有XML 来自build.gradle的摘要Spring 4,Thymeleaf,安全性:未找到WebApplicationContext:未注册ContextLoaderListener,spring,spring-mvc,spring-security,thymeleaf,Spring,Spring Mvc,Spring Security,Thymeleaf,它让我发疯。。。所有的事情都很顺利,我不得不痛苦地从更多不太好的例子中寻找,现在我被一些本该开箱即用的东西困住了 重要提示:我使用Java配置,因此根本没有XML 来自build.gradle的摘要 dependencies { compile 'org.springframework:spring-webmvc:4.2.3.RELEASE', 'org.thymeleaf:thymeleaf-spring4:2.1.4.RELEASE',
dependencies {
compile 'org.springframework:spring-webmvc:4.2.3.RELEASE',
'org.thymeleaf:thymeleaf-spring4:2.1.4.RELEASE',
'com.fasterxml.jackson.core:jackson-databind:2.6.3',
'com.google.guava:guava:18.0',
'org.springframework.security:spring-security-config:4.0.3.RELEASE',
'org.springframework.security:spring-security-web:4.0.3.RELEASE',
'org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.2.RELEASE'
}
WebMvcConfigurationAdapter中有趣的部分
@Configuration
@ComponentScan("de.mypackage")
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
@Bean
IDialect springSecurityDialect() {
return new SpringSecurityDialect();
}
@Bean
@Inject
SpringTemplateEngine templateEngine(final CustomTemplateResolver customTemplateResolver,
final ServletContextTemplateResolver servletContextTemplateResolver,
final IDialect springSecurityDialect) {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(customTemplateResolver);
templateEngine.addTemplateResolver(servletContextTemplateResolver);
templateEngine.addDialect(springSecurityDialect);
return templateEngine;
}
}
public final class WebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(final ServletContext servletContext) {
log.debug("start up {}", servletContext);
try (
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext()) {
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
final Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.setLoadOnStartup(1);
dynamic.addMapping("/");
}
}
}
@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
private static final String LOGIN_URL = "/#login";
@Inject UserDetailsService userService;
@Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.anonymous().principal(getAnonymousUser()).authorities("ROLE_ANOYMOUS");
final String adminAccess = String.format("hasAnyRole('ROLE_%s', 'ROLE_%s')",
Role.SYSTEM_ADMINISTRATOR, Role.USER_ADMINISTRATOR);
log.debug("Configure admin access: {}", adminAccess);
http.authorizeRequests().antMatchers("/admin/**").access(adminAccess).and().formLogin()
.loginPage(LOGIN_URL);
final String systemAdminAccess = String.format("hasRole('ROLE_%s')", Role.SYSTEM_ADMINISTRATOR);
log.debug("Configure system admin access: {}", systemAdminAccess);
http.authorizeRequests().antMatchers("/rest/templates/**").access(systemAdminAccess).and()
.formLogin().loginPage(LOGIN_URL);
}
Principal getAnonymousUser() {
final Principal principal = () -> "guest";
return principal;
}
@Bean
AuthenticationManager getAuthenticationManager() throws Exception {
log.debug("Authentication manager configured");
return authenticationManager();
}
@Bean
PasswordEncoder passwordEncoder() {
final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(12);
return passwordEncoder;
}
}
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {}
强制性的WebApplicationInitializer
@Configuration
@ComponentScan("de.mypackage")
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
@Bean
IDialect springSecurityDialect() {
return new SpringSecurityDialect();
}
@Bean
@Inject
SpringTemplateEngine templateEngine(final CustomTemplateResolver customTemplateResolver,
final ServletContextTemplateResolver servletContextTemplateResolver,
final IDialect springSecurityDialect) {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(customTemplateResolver);
templateEngine.addTemplateResolver(servletContextTemplateResolver);
templateEngine.addDialect(springSecurityDialect);
return templateEngine;
}
}
public final class WebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(final ServletContext servletContext) {
log.debug("start up {}", servletContext);
try (
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext()) {
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
final Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.setLoadOnStartup(1);
dynamic.addMapping("/");
}
}
}
@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
private static final String LOGIN_URL = "/#login";
@Inject UserDetailsService userService;
@Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.anonymous().principal(getAnonymousUser()).authorities("ROLE_ANOYMOUS");
final String adminAccess = String.format("hasAnyRole('ROLE_%s', 'ROLE_%s')",
Role.SYSTEM_ADMINISTRATOR, Role.USER_ADMINISTRATOR);
log.debug("Configure admin access: {}", adminAccess);
http.authorizeRequests().antMatchers("/admin/**").access(adminAccess).and().formLogin()
.loginPage(LOGIN_URL);
final String systemAdminAccess = String.format("hasRole('ROLE_%s')", Role.SYSTEM_ADMINISTRATOR);
log.debug("Configure system admin access: {}", systemAdminAccess);
http.authorizeRequests().antMatchers("/rest/templates/**").access(systemAdminAccess).and()
.formLogin().loginPage(LOGIN_URL);
}
Principal getAnonymousUser() {
final Principal principal = () -> "guest";
return principal;
}
@Bean
AuthenticationManager getAuthenticationManager() throws Exception {
log.debug("Authentication manager configured");
return authenticationManager();
}
@Bean
PasswordEncoder passwordEncoder() {
final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(12);
return passwordEncoder;
}
}
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {}
我的Web安全配置适配器版本
@Configuration
@ComponentScan("de.mypackage")
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
@Bean
IDialect springSecurityDialect() {
return new SpringSecurityDialect();
}
@Bean
@Inject
SpringTemplateEngine templateEngine(final CustomTemplateResolver customTemplateResolver,
final ServletContextTemplateResolver servletContextTemplateResolver,
final IDialect springSecurityDialect) {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(customTemplateResolver);
templateEngine.addTemplateResolver(servletContextTemplateResolver);
templateEngine.addDialect(springSecurityDialect);
return templateEngine;
}
}
public final class WebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(final ServletContext servletContext) {
log.debug("start up {}", servletContext);
try (
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext()) {
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
final Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.setLoadOnStartup(1);
dynamic.addMapping("/");
}
}
}
@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
private static final String LOGIN_URL = "/#login";
@Inject UserDetailsService userService;
@Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.anonymous().principal(getAnonymousUser()).authorities("ROLE_ANOYMOUS");
final String adminAccess = String.format("hasAnyRole('ROLE_%s', 'ROLE_%s')",
Role.SYSTEM_ADMINISTRATOR, Role.USER_ADMINISTRATOR);
log.debug("Configure admin access: {}", adminAccess);
http.authorizeRequests().antMatchers("/admin/**").access(adminAccess).and().formLogin()
.loginPage(LOGIN_URL);
final String systemAdminAccess = String.format("hasRole('ROLE_%s')", Role.SYSTEM_ADMINISTRATOR);
log.debug("Configure system admin access: {}", systemAdminAccess);
http.authorizeRequests().antMatchers("/rest/templates/**").access(systemAdminAccess).and()
.formLogin().loginPage(LOGIN_URL);
}
Principal getAnonymousUser() {
final Principal principal = () -> "guest";
return principal;
}
@Bean
AuthenticationManager getAuthenticationManager() throws Exception {
log.debug("Authentication manager configured");
return authenticationManager();
}
@Bean
PasswordEncoder passwordEncoder() {
final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(12);
return passwordEncoder;
}
}
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {}
结果证明,这个模板不起作用
<meta th:name="${_csrf.parameterName}" th:content="${_csrf.token}" />
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
现在这也起作用了
但是,与往常一样,下一个问题只有一步。这很好:
<li th:if="${#authentication.name == 'guest'}"><a href="#login">Anmelden</a></li>
我没有主意了,所以再见…这只是少了一小块
public final class WebAppInitializer implements WebApplicationInitializer {
private static final Logger log = LoggerFactory.getLogger(WebAppInitializer.class);
@Override
public void onStartup(final ServletContext servletContext) {
log.debug("start up {}", servletContext);
try (
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext()) {
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
servletContext.addListener(new ContextLoaderListener(ctx));
final Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.setLoadOnStartup(1);
dynamic.addMapping("/");
}
}
}
查看
servletContext.addListener
是否已阅读堆栈跟踪?它实际上是在告诉你什么是错的。。。您只有一个DispatcherServlet
noContextLoaderListener
。是的,我知道它没有ContextLoaderListener
hasRole(“'ROLE\u ANONYMOUS”)
拼写错误应该是ROLE\u ANONYMOUS
与错误无关,因为此角色也可以命名为“hans\u wurst”,因此无法工作;)