Create a login page
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Test</title> <script src="static/js/jquery-1.10.2.min.js"></script> <script src="static/js/app-controller.js"></script> </head> <body> <div>Login</div> <form name="f" action="<c:url value="/j_spring_security_check"/>" method="POST"> <label for="password">Username</label> <input type="text" id="j_username" name="j_username"><br/> <label for="password">Password</label> <input type="password" id="j_password" name="j_password"><br/> <input type="submit" value="Validate"> <input name="reset" type="reset"> <input type="hidden" id="${_csrf.parameterName}" name="${_csrf.parameterName}" value="${_csrf.token}"/> </form> <hr/> <c:if test="${param.error != null}"> <div> Failed to login. <c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}"> Reason: <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" /> </c:if> </div> </c:if> <hr/> <input type="button" value="Echo" id="echo" name="echo" onclick="AppController.echo();"> <div id="echoContainer"></div> </body> </html>
Declare a WebSecurityConfigurer HERE IS WHERE I WAS MISSING j_username AND j_password
@Configuration @EnableWebSecurity @ComponentScan(basePackages = {"com.sample.init.security"}) public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Inject private AuthenticationProvider authenticationProvider; @Inject public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers( "/resources/**", "/static/**", "/j_spring_security_check", "/AppController/echo.html").permitAll() .anyRequest().authenticated() .and() .formLogin() .usernameParameter("j_username") /* BY DEFAULT IS username!!! */ .passwordParameter("j_password") /* BY DEFAULT IS password!!! */ .loginProcessingUrl("/j_spring_security_check") .loginPage("/") .defaultSuccessUrl("/page") .permitAll() .and() .logout() .permitAll(); } @Override public void configure(WebSecurity web) throws Exception { web .ignoring() .antMatchers("/static/**"); } }
Declare a WebMvcConfigurer
@EnableWebMvc @Configuration @ComponentScan(basePackages = { "com.app.controller", "com.app.service", "com.app.dao" }) public class WebMvcConfigurer extends WebMvcConfigurerAdapter { @Bean public ViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/view/"); viewResolver.setSuffix(".jsp"); return viewResolver; } @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/page").setViewName("page"); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("static/**").addResourceLocations("static/"); } }
Declare a Security Initializer
public class SecurityWebAppInitializer extends AbstractSecurityWebApplicationInitializer { }
Declare an App Initialzer
public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[]{WebSecurityConfigurer.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[]{WebMvcConfigurer.class, DataSourceConfigurer.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
Implement your custom Authentication Provider
@Component @ComponentScan(basePackages = {"com.app.service"}) public class CustomAuthenticationProvider implements AuthenticationProvider { private static final Logger LOG = LoggerFactory.getLogger(CustomAuthenticationProvider.class); @Inject private AppService service; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { //Thread.dumpStack(); String username = authentication.getName(); String password = authentication.getCredentials().toString(); String message = String.format("Username: '%s' Password: '%s'", username, password); UserBean userBean = service.validate(username, password); LOG.debug(message); if (userBean != null) { List<GrantedAuthority> grantedAuths = new ArrayList<>(); grantedAuths.add(new SimpleGrantedAuthority("USER")); return new UsernamePasswordAuthenticationToken(userBean, authentication, grantedAuths); } else { String error = String.format("Invalid credentials [%s]", message); throw new BadCredentialsException(error); } } @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } }
I am skipping EchoController, AppService, AppDao and UserBean.
Thanks.
In 3.2 version post parameters have changed from j_username to username and j_password to password. The login url has also changed from /j_spring_security_check to /login.
See this link for the explanation of why this change was implemented: http://docs.spring.io/spring-security/site/docs/3.2.0.RELEASE/reference/htmlsingle/#jc-httpsecurity. These are the changes:
GET /login renders the login page instead of /spring_security_login
POST /login authenticates the user instead of /j_spring_security_check
The username parameter defaults to username instead of j_username
The password parameter defaults to password instead of j_password
And this for an example of a login form: http://docs.spring.io/spring-security/site/docs/3.2.0.RELEASE/reference/htmlsingle/#jc-form