Search code examples
spring-mvcspring-bootspring-securityfreemarker

Spring-boot Spring-security Freemarker login success 404 error


I am using Spring boot + spring security + Freemarker.

I have a 2 part question.

  1. I have trouble with CSRF token injected into my page. I think i do not get it because i cannot use form:form tag in freemarker.
  2. If i Disable csrf, it takes me to a 404 page after success login.

I think i am wrong somewere in config

Code copied below

Application.java

@ComponentScan("in.co.mmbf.loanstar")
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

  public static void main(String[] args) throws Exception {
      new SpringApplicationBuilder(Application.class).run(args);
  }


  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(Application.class);
  }
}

ApplicationConfig.java

@Configuration
public class ApplicationConfig extends WebMvcConfigurerAdapter {

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    //registry.addRedirectViewController("/", "home");
    registry.addViewController("/home").setViewName("home");
    registry.addViewController("/login").setViewName("login");
    registry.addViewController("/error").setViewName("error");
    registry.addViewController("/admin").setViewName("admin");
}


@Bean
public FreeMarkerConfigurer freemarkerConfig() throws IOException, TemplateException {
    FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();
    factory.setTemplateLoaderPaths(new String[]{"classpath:org/springframework/web/servlet/view/freemarker/", "classpath:/templates/", "/templates"});
    factory.setDefaultEncoding("UTF-8");
    factory.setPreferFileSystemAccess(false);
    FreeMarkerConfigurer result = new FreeMarkerConfigurer();
    result.setConfiguration(factory.createConfiguration());
    return result;
}
}

ApplicationSecurity.java

@Configuration
@EnableWebSecurity
public class ApplicationSecurity extends WebSecurityConfigurerAdapter implements AuthenticationSuccessHandler {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf().disable()
    .authorizeRequests()
        .antMatchers("/", "/resources/**").permitAll()
        .anyRequest().authenticated()
        .and()
    .formLogin()
        .loginPage("/login")
        .permitAll()
        .and()
    .logout()
        .permitAll();
}

@Override
public void configure(WebSecurity web) throws Exception {
  web.ignoring().antMatchers("/js/**", "/css/**", "/img/**", "favicon.ico");
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
    auth.inMemoryAuthentication().withUser("admin").password("password").roles("USER", "ADMIN");
}

@Override
public void onAuthenticationSuccess(HttpServletRequest request,
        HttpServletResponse response, Authentication authentication)
        throws IOException, ServletException {
    Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
    if (roles.contains("ADMIN")){
        response.sendRedirect("/Admin");
        return;
    }
    response.sendRedirect("/home");
}
}

login.ftl

<!DOCTYPE html>
<html>
<head>
<title>MMBF Loan Star - Login</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/bootstrap.css" />
<link rel="stylesheet" href="css/custom/login.css">
<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/bootstrap.js" type="text/javascript"></script>
<#import "/spring.ftl" as spring/>
</head>
<body onload="document.loginForm.username.focus();">

	<div id="fullscreen_bg" class="fullscreen_bg"></div>

	<div class="container">

		<form class="form-signin" name="loginForm" action="/loanstar/login" method="post">
			<h1 class="form-signin-heading text-muted">Sign In</h1>
			<#if RequestParameters.error??>
				<div class="alert alert-danger" align="center">
				  <strong>Invalid Login!</strong><br>Invalid username or password
				</div>
			<#elseif RequestParameters.logout??>
				<div class="alert alert-info" align="center">
				  <strong>Logged out!</strong><br>You have Logged out of Loanstar
				</div>
			</#if>
			
			<input id="username" name="username" type="text" class="form-control" placeholder="Username" required autofocus> 
			<input id="password" name="password" type="password" class="form-control" placeholder="Password" required>
			<button class="btn btn-lg btn-primary btn-block" type="submit">Sign In</button>
		</form>

	</div>
</body>
</html>

home.ftl

<#import "/layout/defaultLayout.ftl" as layout>
<@layout.pagelayout title="Home">
  <div><h1>Hello Dude</h1></div>
</@layout.pagelayout>

application.properties

server.contextPath=/loanstar
#security.basic.enabled=false
spring.mvc.favicon.enabled=false
spring.freemarker.template-loader-path=/
spring.freemarker.suffix=.ftl

Solution

  • Here is the PR, it can login success, and redirect to home successfully.

    But you'd better to separate the success handler in another class, not in config.

    And about the tags issue please see here