Spring boot security authentication examples with source code are explained here. For authentication default login page, http basic popup or custom login page can be easily configured in spring security using spring boot. User details can be served from database, in-memory or even from properties file. In this article, we will discuss and built each of this example. It clearly means that we are going to multiple examples for implementing spring security authentication.
Spring boot security authentication is enabled by using the @EnableWebSecurity annotation. The abstract class WebSecurityConfigurerAdapter is extended and the configure method is overridden, which enforces the security to the application’s endpoints. In configure method, spring boot security authentication type is specified to avoid unauthenticated access. A filter is implemented and hooked in httpsecurity to inject the user service to provide user details to authenticate and authorize.
- What is Spring Security
- spring-boot-starter-security Maven dependency
- spring-boot-starter-security Gradle dependency
- What is WebSecurityConfigurerAdapter in spring boot
- What is @EnableWebSecurity in spring boot
- Spring boot security Authentication example
- Spring boot basic authentication popup example using properties file
- Spring Boot security default login form inmemory authentication
- Spring Boot security custom login in memory authentication example
- Spring Boot security custom login example with database
- Download Source code for Spring Boot security authentication Examples
- Conclusion
What is Spring Security
Spring Security is a security framework that enables a developer to add security restrictions to Web based applications or as well as Rest based applications using SAML or OAuth2 or custom tokens. The main responsibility of Spring security is to authenticate and authorize the incoming requests, to access any resource which can be a rest api endpoint, mvc url, static resource etc. Spring security is a very powerful framework and provides a high level of customization.
spring-boot-starter-security Maven dependency
The spring-boot-starter-security dependency is the spring boot start project which includes all default configurations required for spring security. It helps a developer a lot with removing the boilerplate code and providing all default configuration values. A developer can customize the spring security easily and can focus better on the main logic in application, without worrying about configuring each and every part of spring security.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
spring-boot-starter-security Gradle dependency
I generally prefer to work with Gradle projects. It’s not much different whether you are using a maven project or a gradle project. I find gradle based projects more neat and clean in terms of readability. If you want to add Gradle dependency then add following one:
compile group: 'org.springframework.boot', name: 'spring-boot-starter-security'
What is WebSecurityConfigurerAdapter in spring boot
The abstract class WebSecurityConfigurerAdapter provides an easy to use base class, when an instance of WebSecurityConfigurer is to be created. The implementation class of WebSecurityConfigurerAdapter customizes the default behavior via overriding the methods. In the implementation class, mostly HttpSecurity and AuthenticationManagerBuilder are configured to secure the application and provide the authentication provider.
What is @EnableWebSecurity in spring boot
The @EnableWebSecurity
annotation is a marker annotation in spring boot security. This annotation enables Spring to find the configuration under @Configuration
or @Component
, which automatically gets applied to the global WebSecurity. The @EnableWebSecurity
annotation is generally used with the class which extends WebSecurityConfigurerAdapter class and overrides its individual methods.
Spring boot security Authentication example
Spring boot basic http authentication is very easy to implement. You can enable http basic authentication popup, default login page or implement custom login page. Authentication mechanism can be injected in spring security which can authenticate from properties file, in-memory credentials or database tables.
For each of these we will discuss multiple Spring MVC examples. Before starting with an example, there are few common steps which will be applicable in all examples:
1. As prerequisites, You should have Java, Gradle and one IDE installed and set up on your machine.
2. Open Spring boot initializer and choose Gradle project with Java 11 and spring boot latest version (avoid using snapshots, use stable version). Provide all the required details and download the zip file.
3. Open the zip file and import the project as a Gradle project into IDE. I generally prefer to use the IntelliJ idea.
4. Open build.gradle file and add following required dependencies.
implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-security'
5. Build the project, so newly added dependencies will be downloaded.
6. Run the application, if your application starts fine then this step is complete.
Spring boot basic authentication popup example using properties file
Spring boot basic http authentication popup is a traditional & easy way to authenticate. If you have a single login user only, then you can use properties files to save the user credentials directly. You don’t need to implement a database or in-memory authentication provider.
Following are the steps to implement http security in spring boot application:
1. Create a class (let’s call this class WebSecurityConfig, but you can name anything) which extends WebSecurityConfigurerAdapter abstract class
2. At WebSecurityConfig’s class level, add two annotations @Configuration
and @EnableWebSecurity
3. In WebSecurityConfig, override configure method to setup HttpSecurity for application.
4. Configure HttpSecurity security to authenticate all requests and apply HttpBasic authentication using httpBasic() method.
5. You class will look like something this:
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); } }
6. Create a sample controller and a default method to test the application. For example, I have created a controller which returns a welcome method.
@Controller public class HelloController { @GetMapping("/") public @ResponseBody String hello(){ return "Hello this is test message."; } }
7. Now time to provide the credentials to the spring security layer, so it can compare and authenticate the user credentials. In application.properties add the credentials like this
spring.security.user.name=technicalsand spring.security.user.password=technicalsand spring.security.user.roles=ADMIN
8. Setup is complete. Now start the application and open it in browser, the default address will be http://localhost:8080 or http://127.0.0.1:8080
9. On opening application in browser, you will see a popup window like shown below:
10. Enter the credentials, as entered in application.properties file which are username = technicalsand and password = technicalsand
11. If you enter correct credentials then you will be able to see the welcome message. If entered username or password is wrong then popup will ask you again to enter the credentials.
Spring Boot security default login form inmemory authentication
Spring security default login page is an inbuilt login page which is provided by spring boot security started project. This page automatically maps the username and password and provides easy authentication. All the error messages and logout options are handled by this page itself.
The inmemory authentication is the mechanism to keep the user credentials in JVM memory itself, but saving over a file or into a database. If you are trying to test something in spring boot or building some kind of proof of concept then usually in-memory authentication is used.
Following are the steps to implement Spring boot security default login page using in memory authentication:
- You should extend WebSecurityConfigurerAdapter abstract class. In our example, we have created a WebSecurityConfig class for this purpose.
- WebSecurityConfig class should have annotations
@Configuration
and@EnableWebSecurity
at class level. - In WebSecurityConfig, Configure HttpSecurity to authenticate all incoming requests and enable spring security default login page.
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin(); }
4. Since we are going to use the in-memory authentication. It’s recommended to use a password encoder for saving passwords in memory or database. Spring security has inbuilt support for BCryptPasswordEncoder. So we can create a bean of it and use it directly.
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
5. In WebSecurityConfig, configure AuthenticationManagerBuilder to set up in-memory credentials.
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .passwordEncoder(new BCryptPasswordEncoder()) .withUser("technicalsand") .password(passwordEncoder().encode("technicalsand")) .roles("ADMIN") .and() .withUser("reader") .password(passwordEncoder().encode("reader1")) .roles("USER") ; }
6. Now run the application and open the browser, navigate to http://localhost:8080 or http://127.0.0.1:8080 You will see a login page like this:
7. Enter the wrong credentials first and see it will show an error for bad credentials.
8. Enter the correct credentials which are (technicalsand, technicalsand) and you will see the welcome message on screen.
Spring Boot security custom login in memory authentication example
Spring security custom login page is a page which is entirely created by the developer and customized as per his own needs. It is very common that you need to have a custom login page to show your own branding, customized options to login or some other information to display on the login page.
In this example, we will implement a custom login page using Thymeleaf. Thymeleaf is a Java based server-side modern template engine, used for both standalone and web applications.
Following are the steps to implement Spring boot security with a custom login page with in-memory authentication and Thymeleaf.
1. First of all, add are required dependencies in build,gradle file for Spring security and thymeleaf.
implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
2. Password encoder and in-memory authentication steps will remain the same as in the previous example. So skipping these steps.
3. Create a home page under resources/templates directory.
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body style="text-align: center;"> <h1>Welcome to TechnicalSand's Spring Boot Security Example</h1> <a href="/logout">logout</a> </body> </html>
4. Create a login page under resources/templates directory.
<html xmlns:th="https://www.thymeleaf.org"> <head > <title>Please Login</title> </head> <body> <div th:fragment="content"> <form name="f" th:action="@{/login}" method="post"> <fieldset> <legend>Please Login here</legend> <div th:if="${param.error}" class="alert alert-error"> Invalid username and password. </div> <div th:if="${param.logout}" class="alert alert-success"> You have been logged out, Please login again. </div> <label for="username">Username</label> <input type="text" id="username" name="username" value="technicalsand"/> <label for="password">Password</label> <input type="password" id="password" name="password" value="technicalsand"/> <div class="form-actions"> <button type="submit" class="btn">Log in</button> </div> </fieldset> </form> </div> </body> </html>
5. Create a controller to provide mappings for home page and login page. At homepage, we will show the name of the logged in user.
@Controller public class HelloController { @GetMapping("/") public ModelAndView home(Principal principal) { return (new ModelAndView("home")).addObject("principal", principal); } @GetMapping("/login") public ModelAndView login() { return new ModelAndView("login"); } }
6. Now time to configure HttpSecurity in WebSecurityConfig class. After the formLogin() method add a loginPage method and provide the mapping uri for login page. Since everyone can see the login page to enter credentials, so on loginPage add permitAll() method.
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/resources/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")); }
7. In the above configuration, we have handled logout to be redirected to the login page with logout messages. The last line of above code represents this configuration.
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
8. Run the application and open via http://127.0.0.1:8080 or http://localhost:8080
9. You should be able to see the login page like this.
10. Enter the correct credentials (technicalsand, technicalsand) and you should see the welcome screen.
11. On the welcome screen, you can click the logout link. On logout, you will be redirected to the login page back.
Spring Boot security custom login example with database
Spring boot security with database authentication is the most preferred way in standard applications. Database can be any, but the implementation approach in spring boot security remains the same.
In our example, we will implement a custom login with MySql database authentication. We will also go through the steps if you want to do authentication with other databases like postgres, Oracle etc.
Following are the steps for Spring boot authentication example with database:
1. Custom login is implemented in the previous example. All the steps will remain the same, so you can refer those again. We can skip those steps and discuss other things which needs to be done specifically for database authentication.
2. For database authentication, you need to add 2 new dependencies in build.gradle file. Spring boot starter data jpa dependency is required to configure for datasource requirements. Since we are going to use MySql , we need to provide MySql java connector dependency, which is basically MySql driver classes.
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' compile 'mysql:mysql-connector-java'
3. Open application.propeties file and database credentials. In my example, i am using a database with the name “demo” and the user name/password is root/root. Please change as per your requirements.
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root
4. Automatically let hibernate create your database tables. You just need to create a blank database (demo database in example) and following hibernate configuration in application.properties will automatically add/update tables on application startup.
spring.jpa.hibernate.ddl-auto=update
5. Every logged in user, should have a role. We will create a role table where all the roles will be added, which can be assigned to the user. Create a Role class as following:
@Entity public class Role { @GeneratedValue(strategy = GenerationType.AUTO) @Id private Long id; private String roleName; public Role(){} public Role(String roleName){ this.roleName = roleName; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } }
6. We need a user domain class, which will map to a table in the database. So create User class as following:
@Entity public class User { @GeneratedValue(strategy = GenerationType.AUTO) @Id private Long id; private String username; private String password; private boolean disabled = false; private LocalDateTime createdAt = LocalDateTime.now(); @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private List<Role> roles; public User(){} public User( String username, String password, Role role){ this.username = username; this.password = password; roles =new ArrayList<>(); roles.add(role); } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isDisabled() { return disabled; } public void setDisabled(boolean disabled) { this.disabled = disabled; } public LocalDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } }
7. In user class, we have added Many to Many mapping between user and role. So, this mapping will create a third table user_role which will hold all user ids with their role ids.
8. Now let’s create a RoleRepository which will extend the JpaRepository and provide all standard methods by default.
public interface RoleRepository extends JpaRepository<Role, Long> { }
9. Create a user repository, with a method to find a user with a given username. I have added an additional field for disabled. As we want to login a user, who is an active user only.
public interface UserRepository extends JpaRepository<User, Long> { User findByUsernameAndDisabled(String username, boolean disabled); }
10. Now we need to create a class which implements Spring’s UserDetailsService class and override the method loadUserByUsername() to provide custom implementation of finding the user.
public class UserDetailsServiceImpl implements UserDetailsService { private UserRepository userRepository; public UserDetailsServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; } @Override public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { User user = userRepository.findByUsernameAndDisabled(userName, false); if (user == null) { throw new UsernameNotFoundException("User is not Found"); } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), mapRolesToAuthorities(user.getRoles())); } private Collection<? extends GrantedAuthority> mapRolesToAuthorities(List<Role> roles) { return roles.stream() .map(role -> new SimpleGrantedAuthority(role.getRoleName())) .collect(Collectors.toList()); } }
11. We don’t want to save passwords in the database as plain text due to security reasons. So we want to encrypt the password, so the database password gets saved in encrypted form and Spring security uses it directly as encrypted form. So in WebSecurityConfig, we will create a BCryptPasswordEncoder bean and supply it to the authentication manager to use for password encryptions for incoming passwords from the login page.
12. Since we have created, all the components. Now time to configure these with a security layer. In WebSecurityConfig, Configure AuthenticationManagerBuilder and provide the custom userDetailsServiceImp class.
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired UserRepository userRepository; @Bean public UserDetailsService userDetailsServiceImpl() { return new UserDetailsServiceImpl(userRepository); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsServiceImpl()).passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/resources/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll().logoutRequestMatcher(new AntPathRequestMatcher("/logout")); ; } }
13. Everything is set up now. We need some sample data, so we can login within the application. For this purpose I have created a DemoData class, which automatically inserts data in a database on server startup. This step is purely optional, you can manually insert data or can create a sql script to insert data.
@Component public class DemoData { @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired private PasswordEncoder passwordEncoder; @EventListener public void appReady(ApplicationReadyEvent event) { if(roleRepository.count() ==0 ) { System.out.println("Saving demo data"); Role roleAdmin = new Role("ADMIN"); Role roleUser = new Role("USER"); roleRepository.save(roleAdmin); roleRepository.save(roleUser); User userAdmin = new User("technicalsand", passwordEncoder.encode("password1"), roleAdmin); User userReader = new User("reader", passwordEncoder.encode("reader1"), roleUser); userRepository.save(userAdmin); userRepository.save(userReader); System.out.println("Demo data saved successfully."); } } }
14. Now start the application. Check in the database, your 3 tables (user, role, user_role) should be created. These tables should have 2 users login credentials also.
15. Navigate to http://localhost:8080 or htp://127.0.0.1:8080 and enter correct credentials (technicalsand, technicalsand) and you should be able to see the welcome screen.
16. If you want to change the database to PostGres, Oracle or something else. Then you need to make 2 changes only. In build.properties, remove mysql connector and add supporting connector for your database. In application.properties , change value of spring.datasource.url to database specific url.
Download Source code for Spring Boot security authentication Examples
All the examples mentioned in this article are present on Github. You can download Source code on Github and customize/use for any purpose.
Conclusion
In this article, we have seen different spring boot security authentication examples using basic popup, default login page or custom page. We configure the authentication provider to use user details from properties file, in-memory authentication and database based authentication. We hope this article will help you all.
Pingback: Streaming Data with Spring Boot RESTful Web Service