Search code examples
cssspringspring-bootthymeleaf

Why is signing in to my Spring Boot + Thymeleaf application redirecting to a CSS file?


My Spring Boot application is using Thymeleaf and all works fine until I add a custom CSS stylesheet. As soon as I add the stylesheet to the templats, signing in results in the content of that stylesheet being rendered instead of the page the browser should be redirected to.

The sign in page template:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
    <head>
        <title>Microservice Template</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css">
        <link rel="stylesheet" th:href="@{/css/template.css}" />
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <form th:action="@{/login}" method="post">
            <dialog open>
                <article>
                    <header>
                        <a th:href="@{/}" aria-label="Close" class="close"></a>
                        Sign In
                    </header>
                    <p>
                        <div><label>Username: <input type="text" name="username"/> </label></div>
                        <div><label>Password: <input type="password" name="password"/> </label></div>
                    </p>
                    <footer>
                        <div><input type="submit" value="Sign In"/></div>
                    </footer>
                </article>
            </dialog>
        </form>
    </body>
</html>

Spring MVC configuration:

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }
}

Spring Security configuration

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChains(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((requests) -> requests
                        .requestMatchers("/", "/home").permitAll()
                        .anyRequest().authenticated()
                )
                .formLogin((form) -> form
                        .loginPage("/login")
                        .permitAll()
                )
                .logout((logout) -> logout.permitAll());

        return http.build();
    }

}

Contents of template.css:

body {
    padding: 10px;
}

The file structure:

enter image description here

And this is how the browser looks after signing in:

enter image description here


Solution

  • Spring Security is as safe as possible by design. So it will disallow all access by default and you need to specify what you want to allow (unless you don't apply the defaults then everything is open which seems like a bad idea).

    With this in mind Spring Security is doing exactly what it should do securing anything but / and /home as that is what you stated for your permitAll and nothing else.

    If you want to allow access to your static files you need to include those as well in your permitAll part of the security.