title: spring boot custom login page
body: <p>I am trying to add a custom login page for my boot strap application. I was following <a href="http://docs.spring.io/spring-security/site/docs/3.2.x/guides/form.html" rel="nofollow">this</a> tutorial. I couldn't make work with my custom login page.</p>
  
  <p>Here is my pom.xml:</p>
  
  <pre><code>...
   &lt;dependency&gt;
     &lt;groupId&gt;org.springframework.data&lt;/groupId&gt;
     &lt;artifactId&gt;spring-data-commons&lt;/artifactId&gt;
   &lt;/dependency&gt;
   &lt;dependency&gt;
      &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
      &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
      &lt;scope&gt;test&lt;/scope&gt;
   &lt;/dependency&gt;
   &lt;dependency&gt;
      &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
      &lt;artifactId&gt;spring-boot-starter-security&lt;/artifactId&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
      &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
      &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;/artifactId&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
      &lt;groupId&gt;org.apache.httpcomponents&lt;/groupId&gt;
      &lt;artifactId&gt;httpclient&lt;/artifactId&gt;
      &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
  ...
  </code></pre>
  
  <p>MvcConfig.java</p>
  
  <pre><code>import org.springframework.context.annotation.Configuration;
  import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  
  @Configuration
  public class MvcConfig extends WebMvcConfigurerAdapter {
  
      @Override
      public void addViewControllers(ViewControllerRegistry registry) {
          registry.addViewController("/").setViewName("forward:/index.html");
  
          registry.addViewController("/login").setViewName("login");
      }
  
  }
  </code></pre>
  
  <p>FrontendApp.java:</p>
  
  <pre><code>import org.slf4j.LoggerFactory;
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  import org.springframework.context.annotation.Import;
  
  import ch.qos.logback.classic.Logger;
  
   @SpringBootApplication
   @Import(value = MvcConfig.class)
   public class FrontendApp {
  
        private static Logger logger = (Logger) LoggerFactory.getLogger(FrontendApp.class);
  
        public static void main(String[] args) {
  
            SpringApplication app = new SpringApplication(FrontendApp.class);
            app.run(args);
       }
  
  }
  </code></pre>
  
  <p>SecurityConfiguration.java</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
  public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
      @Autowired
      private CustomAuthenticationProvider customAuthenticationProvider;
  
      @Autowired
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
           auth.authenticationProvider(this.customAuthenticationProvider);
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
           http
              .authorizeRequests()
              .antMatchers("/css/**").permitAll()
              .antMatchers("/resources/**").permitAll()
              .antMatchers("**").permitAll()
              .antMatchers("/login").permitAll()
          .anyRequest().authenticated().and()
          .formLogin()
          .loginPage("/login");
      }
  
  }
  </code></pre>
  
  <p>I opened all the url's so Ican just check whether I can see /login or not.
  CustomAuthenticationProvider.java</p>
  
  <pre><code>@Component
  public class CustomAuthenticationProvider implements AuthenticationProvider {    
  
      private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);
  
  
      public CustomAuthenticationProvider() {
          logger.info("*** CustomAuthenticationProvider created");
      }
  
      @Override
      public boolean supports(Class&lt;?&gt; authentication) {
           return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
      }
  
      @Override
      public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  
          if(authentication.getName().equals("karan")  &amp;&amp; authentication.getCredentials().equals("saman")) {
              List&lt;GrantedAuthority&gt; grantedAuths = new ArrayList&lt;&gt;();
              grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
              grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
              return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(), grantedAuths);
           } else {
                return null;
           }
      }
  
  }
  </code></pre>
  
  <p>When I try localhost:8080/login I will get the following error:</p>
  
  <pre><code>Whitelabel Error Page
  
  This application has no explicit mapping for /error, so you are seeing this as a fallback.
  There was an unexpected error (type=Internal Server Error, status=500).
  Error resolving template "login", template might not exist or might not be accessible by any of the configured Template Resolvers
  </code></pre>
  
  <p>However when I try localhost:8080/ it will successfully redirect to index.html as I specified in MvcConfig.java.</p>
  
  <p>Here is my login.html code:</p>
  
  <pre><code>   &lt;html xmlns="http://www.w3.org/1999/xhtml" 
           xmlns:th="http://www.thymeleaf.org" 
           xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
           xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"&gt;
  
  &lt;head&gt;
      &lt;meta charset="utf-8" /&gt;
      &lt;title&gt;k&lt;/title&gt; 
  &lt;/head&gt;
  </code></pre>
  
  <p>I paste my login.html in /src/main/resources/templates and /src/main/webapp/ and /src/main/webapp/templates it still didn't work!</p>