Search code examples
javaspringspring-bootthymeleaf

Springboot won't load CSS folders after implementing web security & mvc configuration


I tried to implement this example but in my case, i have some static css files i have to include.

Regarding the css issue i tried putting th:href="@{PATH} attribute on html links but it didn't work for me.

My application on the security side, works almost as the example above.

In my project instead of being redirected to hello.html i'm being redirected to an image url.

This is the html templates, in which i used Thymeleaf:

  • login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="https://www.thymeleaf.org"
    xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Speak Up</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--===============================================================================================-->
<link rel="icon" type="image/png"
    href="logincss/images/icons/favicon.png" />
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/vendor/bootstrap/css/bootstrap.min.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/fonts/font-awesome-4.7.0/css/font-awesome.min.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/fonts/iconic/css/material-design-iconic-font.min.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/vendor/animate/animate.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/vendor/css-hamburgers/hamburgers.min.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/vendor/animsition/css/animsition.min.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/vendor/select2/select2.min.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css"
    href="logincss/vendor/daterangepicker/daterangepicker.css">
<!--===============================================================================================-->
<link rel="stylesheet" type="text/css" href="logincss/css/util.css">
<link rel="stylesheet" type="text/css" href="logincss/css/main.css">

<!--===============================================================================================-->
</head>
<body>

    <div class="limiter">
        <div class="container-login100"
            style="background-image: url('logincss/images/bg-01.jpg');">
            <div class="wrap-login100">

                <form class="login100-form validate-form" action="#"
                    th:action="@{/login}" method="post">


                    <span class="login100-form-logo"> <img
                        src="logincss/images/icons/favicon.png" />
                    </span> <span class="login100-form-title p-b-34 p-t-27"> Log in </span>

                    <!-- This is from the Spring Security example-->
                    <div th:if="${param.error}">Invalid username and password.</div>
                    <div th:if="${param.logout}">You have been logged out.</div>

                    <div class="wrap-input100 validate-input"
                        data-validate="Enter username">
                        <input class="input100" type="text" name="username"
                            placeholder="Username"> <span class="focus-input100"
                            data-placeholder="&#xf207;"></span>
                    </div>

                    <div class="wrap-input100 validate-input"
                        data-validate="Enter password">
                        <input class="input100" type="password" name="password"
                            placeholder="Password"> <span class="focus-input100"
                            data-placeholder="&#xf191;"></span>
                    </div>



                    <div class="contact100-form-checkbox">
                        <input class="input-checkbox100" id="ckb1" type="checkbox"
                            name="remember-me"> <label class="label-checkbox100"
                            for="ckb1"> Remember me </label>
                    </div>

                    <div class="container-login100-form-btn">
                        <button class="login100-form-btn">Login</button>
                    </div>

                    <div class="text-center p-t-90">
                        <a class="txt1" href="#"> Forgot Password? </a> <br> <a
                            class="txt1" href="/register"> Don't have an account?
                            Register now! </a>
                    </div>
                </form>
            </div>
        </div>
    </div>


    <div id="dropDownSelect1"></div>

    <!--===============================================================================================-->
    <script src="logincss/vendor/jquery/jquery-3.2.1.min.js"></script>
    <!--===============================================================================================-->
    <script src="logincss/vendor/animsition/js/animsition.min.js"></script>
    <!--===============================================================================================-->
    <script src="logincss/vendor/bootstrap/js/popper.js"></script>
    <script src="logincss/vendor/bootstrap/js/bootstrap.min.js"></script>
    <!--===============================================================================================-->
    <script src="logincss/vendor/select2/select2.min.js"></script>
    <!--===============================================================================================-->
    <script src="logincss/vendor/daterangepicker/moment.min.js"></script>
    <script src="logincss/vendor/daterangepicker/daterangepicker.js"></script>
    <!--===============================================================================================-->
    <script src="logincss/vendor/countdowntime/countdowntime.js"></script>
    <!--===============================================================================================-->
    <script src="logincss/js/main.js"></script>

</body>
</html>
  • hello.html in which i'm not being redirected (although the authentication works)

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
      xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>
    </body>

  • home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>

        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>

  • My 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");

    }

     @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry
                    .addResourceHandler("/resources/**")
                    .addResourceLocations("/classpath:/static/");
        }

}

  • my class extending WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/","/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();


    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        UserDetails user =
             User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build();

        return new InMemoryUserDetailsManager(user);
    }
}
  • Spring security dependencies:

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

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

  • Thymeleaf dependancy:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>
  • Project's Structure:

enter image description here

Only hello.html home.html and login.html are being used for this example.

Output

This is what the login.html looks like without logincss folder:

enter image description here

And upon successful login i'm being redirected here(instead of hello.html):

enter image description here

How can i correctly refer to the static css and redirect the user to hello.html?

I'm sorry for the long post.


Solution

  • You need to allow access to logincss and any other static resources (js, images, etc) directories in the Spring Security configuration. In your configure method, add .antMatchers("/logincss/**").permitAll().

    Similarly add antMatcher for "/templates/**".

    Reference configuration in Spring Documentation for additional reading here.

    As regards redirection on successful login to hello.html, you need to add the configuration for defaultSuccessUrl("/hello.html"). Reference Documentation here.