In this spring security 5 tutorial, learn to add custom login form based security to our Spring WebMVC application. I am using Spring security 5 to build this example. This tutorial additionally discusses logout from the session.
1. Include spring security 5 dependencies
Include spring security jars. I am using maven so added respective dependencies for spring security version 5.0.7.RELEASE.
<properties> <failOnMissingWebXml>false</failOnMissingWebXml> <spring.version>5.2.0.RELEASE</spring.version> </properties> <!-- Spring MVC Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring Security Core --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring Security Config --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring Security Web --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${spring.version}</version> </dependency>
2. Create Spring Security Configuration
2.1. Configure Authentication and URL Security
- I have created this simple security configuration and added two demo users ‘
user
‘ and ‘admin
‘. @EnableWebSecurity
enables Spring Security’s web security support, and also provides the Spring MVC integration.WebSecurityConfigurerAdapter
provides a set of methods that are used to enable specific web security configuration.configure(HttpSecurity http)
is used to secure different URLs that need security.- It configures custom login page at URL
/login
. If username/password match then request is redirected to/home
, else login page is refreshed with respective error message. - It also configures logout from session. After logout, user is redirected to login page again.
I have used in-memory authentication using
auth.inMemoryAuthentication()
. You can configure JDBC auth usingauth.jdbcAuthentication()
or LDAP auth usingauth.ldapAuthentication()
.
package com.howtodoinjava.demo.spring.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired PasswordEncoder passwordEncoder; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .passwordEncoder(passwordEncoder) .withUser("user").password(passwordEncoder.encode("123456")).roles("USER") .and() .withUser("admin").password(passwordEncoder.encode("123456")).roles("USER", "ADMIN"); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login") .permitAll() .antMatchers("/**") .hasAnyRole("ADMIN", "USER") .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/home") .failureUrl("/login?error=true") .permitAll() .and() .logout() .logoutSuccessUrl("/login?logout=true") .invalidateHttpSession(true) .permitAll() .and() .csrf() .disable(); } }
Read More: Spring Security XML Config for Login Form
2.2. Bind spring security to web application
In Spring web applications, security is implemented using DelegatingFilterProxy
. To register it, with spring container in Java configuration, you shall use AbstractSecurityWebApplicationInitializer
.
The spring will detect the instance of this class during application startup, and register the DelegatingFilterProxy
to use the springSecurityFilterChain
before any other registered Filter. It also register a ContextLoaderListener
.
package com.howtodoinjava.demo.spring.config; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer { //no code needed }
Also, include SecurityConfig
to AppInitializer
.
package com.howtodoinjava.demo.spring.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { HibernateConfig.class, SecurityConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
3. Add Custom Login Form
3.1. Login Controller
Add the login controller method to handle login and logout requests.
package com.howtodoinjava.demo.spring.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class LoginController { @RequestMapping(value = "/login", method = RequestMethod.POST) public String loginPage(@RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout", required = false) String logout, Model model) { String errorMessge = null; if(error != null) { errorMessge = "Username or Password is incorrect !!"; } if(logout != null) { errorMessge = "You have been successfully logged out !!"; } model.addAttribute("errorMessge", errorMessge); return "login"; } @RequestMapping(value="/logout", method = RequestMethod.GET) public String logoutPage (HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null){ new SecurityContextLogoutHandler().logout(request, response, auth); } return "redirect:/login?logout=true"; } }
3.2. login.jsp
Create login.jsp
file which will accept username
and password
; and post them to URL /login
.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <body onload='document.loginForm.username.focus();'> <h1>Spring Security 5 - Login Form</h1> <c:if test="${not empty errorMessge}"><div style="color:red; font-weight: bold; margin: 30px 0px;">${errorMessge}</div></c:if> <form name='login' action="/login" method='POST'> <table> <tr> <td>UserName:</td> <td><input type='text' name='username' value=''></td> </tr> <tr> <td>Password:</td> <td><input type='password' name='password' /></td> </tr> <tr> <td colspan='2'><input name="submit" type="submit" value="submit" /></td> </tr> </table> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form> </body> </html>
4. Spring Security 5 Login Form Demo
- Start the application with maven run command
tomcat7:run
. Launch homepagehttp://localhost:8080/home
. It will redirected to login pagehttp://localhost:8080/login
.Login Form - Enter INCORRECT username or password. A login error message will be displayed.
Incorrect username or password - Enter CORRECT username and password combination.
user
and123456
. Home page will be displayed.Home Page - Click on logout button. The user will be logged out and redirected back to the login page.
Logged Out
Happy Learning !!
rinilnath
The sample code given has home.jsp but nothing relates to the output when we execute the GitHub checkout, it will not work correctly.
Can you please correct the sample to match like to show in the output?
Lokesh Gupta
I will check this out, again.
mohammad
thankyou very much, i need spring security JWT config example too.
raja babu
I use noOpPasswordEncoder to not to encrypt my password but I wasn’t able to redirect it to the page.
raja babu
I face the same issue, I sout the login controller to see whether it is redirecting to another page or not. I found out that it’s redirecting to the same page again and again.
Shashank Gupta
Tried running the code.
After login, the login page is being displayed again and again with no redirection to homepage.