具有多个Thymleaf ViewResolvers的Spring Security自定义登录页面

时间:2017-06-29 02:59:29

标签: java spring spring-boot spring-security

我搜索并搜索过,找不到任何东西。我使用弹簧靴,百里香叶,弹簧安全工作的公司项目的PoC。

如果我在 spring security config 中设置登录页面,如

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
    protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .antMatchers("/admin/**").hasAnyRole("ADMIN")
            .antMatchers("/user/**").hasAnyRole("USER")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage ("/login")
            .permitAll().defaultSuccessUrl ("/home")
            .and()
            .logout()
            .permitAll();
}

并在我的登录页面(HTML)中传递:

.... 
    <link rel="stylesheet" type="text/css"  href="/styles.css" />
....

简单的css文件:

  #test {
      font-family: Arial, sans-serif;
      padding-left: 1em;
      background-color: /*[[${backgroundColor}]]*/ pink !important;
    }

我得到日志

2017-06-28 21:50:29.436  INFO 24430 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 12 ms
2017-06-28 21:50:29.436 DEBUG 24430 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Servlet 'dispatcherServlet' configured successfully
2017-06-28 21:50:29.476 DEBUG 24430 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/login]
2017-06-28 21:50:29.477 DEBUG 24430 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /login
2017-06-28 21:50:29.492 DEBUG 24430 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public java.lang.String sample.multimodule.generic.web.login.login(org.springframework.ui.Model)]
2017-06-28 21:50:29.492 DEBUG 24430 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/login] is: -1
2017-06-28 21:50:29.505 DEBUG 24430 --- [nio-8080-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Requested media types are [text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8] based on Accept header types and producible media types [*/*])
2017-06-28 21:50:29.509 DEBUG 24430 --- [nio-8080-exec-2] o.s.w.servlet.view.BeanNameViewResolver  : Found matching bean for view name 'login' - to be ignored since it does not implement View
2017-06-28 21:50:29.510 DEBUG 24430 --- [nio-8080-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Returning [org.thymeleaf.spring4.view.ThymeleafView@5d886361] based on requested media type 'text/html'
2017-06-28 21:50:29.511 DEBUG 24430 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Rendering view [org.thymeleaf.spring4.view.ThymeleafView@5d886361] in DispatcherServlet with name 'dispatcherServlet'
2017-06-28 21:50:29.776 DEBUG 24430 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Successfully completed request
2017-06-28 21:50:29.798 DEBUG 24430 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/login]
2017-06-28 21:50:29.798 DEBUG 24430 --- [nio-8080-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /login
2017-06-28 21:50:29.799 DEBUG 24430 --- [nio-8080-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public java.lang.String sample.multimodule.generic.web.login.login(org.springframework.ui.Model)]
2017-06-28 21:50:29.799 DEBUG 24430 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/login] is: -1
2017-06-28 21:50:29.799 DEBUG 24430 --- [nio-8080-exec-4] o.s.w.s.v.ContentNegotiatingViewResolver : Requested media types are [text/css, */*;q=0.1] based on Accept header types and producible media types [*/*])
2017-06-28 21:50:29.800 DEBUG 24430 --- [nio-8080-exec-4] o.s.w.servlet.view.BeanNameViewResolver  : Found matching bean for view name 'login' - to be ignored since it does not implement View
2017-06-28 21:50:29.800 DEBUG 24430 --- [nio-8080-exec-4] o.s.w.servlet.view.BeanNameViewResolver  : No matching bean found for view name 'login.css'
2017-06-28 21:50:29.800 DEBUG 24430 --- [nio-8080-exec-4] o.s.w.s.v.ContentNegotiatingViewResolver : Returning [org.thymeleaf.spring4.view.ThymeleafView@34f7b639] based on requested media type 'text/css'
2017-06-28 21:50:29.800 DEBUG 24430 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Rendering view [org.thymeleaf.spring4.view.ThymeleafView@34f7b639] in DispatcherServlet with name 'dispatcherServlet'
2017-06-28 21:50:29.819 ERROR 24430 --- [nio-8080-exec-4] org.thymeleaf.TemplateEngine             : [THYMELEAF][http-nio-8080-exec-4] Exception processing template "login [text/html]": An error happened during template parsing (template: "class path resource [templates/css/login]")

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/css/login]")
    at org.thymeleaf.templateparser.text.AbstractTextTemplateParser.parse(AbstractTextTemplateParser.java:174) ~[thymeleaf-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.thymeleaf.templateparser.text.AbstractTextTemplateParser.parseStandalone(AbstractTextTemplateParser.java:92) ~[thymeleaf-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) ~[thymeleaf-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) [thymeleaf-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) [thymeleaf-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.thymeleaf.spring4.view.ThymeleafView.renderFragment(ThymeleafView.java:335) [thymeleaf-spring4-3.0.5.RELEASE.jar:3.0.5.RELEASE]
...
...

我有 ThymeleafConfig

@Configuration
@ConditionalOnClass({SpringTemplateEngine.class})
public class ThymeleafConfig extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter implements ApplicationContextAware {

private ApplicationContext applicationContext;
private static final String UTF8 = "UTF-8";


public void setApplicationContext(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
}


private TemplateEngine templateEngine(ITemplateResolver templateResolver) {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setTemplateResolver(templateResolver);
    return engine;
}

@Bean
public ViewResolver htmlViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setOrder (0);
    resolver.setTemplateEngine(templateEngine(htmlTemplateResolver ()));
    resolver.setCharacterEncoding(UTF8);
    resolver.setContentType("text/html");
    return resolver;
}


private ITemplateResolver htmlTemplateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setOrder (0);
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("classpath:/templates/");
    resolver.setSuffix(".html");
    resolver.setTemplateMode(TemplateMode.HTML);
    resolver.setCacheable(false);
    return resolver;
}

@Bean
public ViewResolver cssViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setOrder (10);
    resolver.setTemplateEngine(templateEngine(cssTemplateResolver ()));
    resolver.setCharacterEncoding(UTF8);
    resolver.setContentType("text/css");
    return resolver;
}


private ITemplateResolver cssTemplateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setOrder (10);
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("classpath:/templates/css/");
    resolver.setSuffix("");
    resolver.setTemplateMode(TemplateMode.CSS);
    resolver.setCacheable(false);
    return resolver;
}



@Bean
public ViewResolver jsViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setOrder (20);
    resolver.setTemplateEngine(templateEngine(jsTemplateResolver ()));
    resolver.setCharacterEncoding(UTF8);
    resolver.setContentType("application/javascript");
    return resolver;
}


private ITemplateResolver jsTemplateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setOrder (20);
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("classpath:/templates/js/");
    resolver.setSuffix("");
    resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
    resolver.setCacheable(false);
    return resolver;
}

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
}

}

和Css控制器:

@Controller
public class CssController {

    @RequestMapping (value = "/styles.css")
    public String mainStyles(Model model, HttpServletResponse response) {
        model.addAttribute("backgroundColor", "blue");
        return "styles.css";
    }

}

如果我删除

....formLogin().loginPage ("/home")

从安全配置中获取并在控制器中正常运行,它可以工作,并且变量会像我期望的那样添加到css文件中。

在Spring Security中指向/ login时,为什么会出现此问题?

*请注意第一次发布,如果格式正确,请道歉。

1 个答案:

答案 0 :(得分:0)

发现问题所在,在使用安全性时不允许访问该文件。

需要在安全配置中添加以下内容:

... 
.antMatchers ("/styles.css").permitAll ()
...