Spring Boot + Security + MySQL (2023) Hello World Example
In this tutorial we will be implementing Spring Boot Security in our application.Spring Security is one of the most important framework used for making enterprise applications. It provides some of the important features which includes user authentication i.e.who you are and authorization i.e. are you authorized to fetch a particular request.
The mysql default schema can be defined as follows- The username in the User class acts as a foreign key for the Authority class.
In this example, i would be implementing basics of Spring Security using a simple example where I would be using mysql default schema for the database configuration. Finally, as a result, a login form will be linked in our application.
-
This will be the standard directory layout for maven project structure-
We need to start by creating a Maven pom.xml(Project Object Model) file. The pom.xml file contains the project configuration details.<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.codeusingjava</groupId> <artifactId>WebSecurityDBConfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>websecurity</name> <description>Spring boot security authentication project</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
The application.properties file is as follows:- All the database related configurations are done in this file.spring.datasource.url=jdbc:mysql://localhost:3300/SecuritySchema?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false spring.datasource.password=**** spring.datasource.username=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.initialize=false spring.jpa.hibernate.ddl-auto=create-drop
Creating the schema file for the database configuration
We use mysql default schema which defines about the users and their authorities assigned.CREATE TABLE UsersTable( username VARCHAR(50) NOT NULL PRIMARY KEY, PASSWORD VARCHAR(200) NOT NULL, email VARCHAR(100) NOT NULL, enabled BOOLEAN NOT NULL ); CREATE TABLE authorities ( username VARCHAR(50) NOT NULL, authority VARCHAR(50) NOT NULL, CONSTRAINT fk_authorities_users FOREIGN KEY(username) REFERENCES UsersTable(username) ); CREATE UNIQUE INDEX ix_auth_username ON authorities (username,authority);
Creating the configuration class for spring security:-
Query to write inside data.sql INSERT into UsersTable(username,password,email,enabled) values ('user','{noop}user','[email protected]',true); INSERT into UsersTable(username,password,email,enabled) values ('admin','{noop}admin','[email protected]',true); INSERT into authorities values ('user','USER'); INSERT into authorities values ('admin','ADMIN');
All the configurations related to HttpSecurity are done inside the configure method().
For the process of authentication of user, AuthenticationManagerBuilder is used.
As we are using mysql database to store users and their authorities, so we use jdbcAuthentication.
WebSecurityConfigurerAdapter is a class which provides several methods by which httpSecurity and WebSecurity can be customised.
PasswordEncoder specifies whether the password is to be stored in its original form or by the manner the password is to be encoded.package com.codeusingjava.websecurity.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; 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.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.DelegatingPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import javax.sql.DataSource; @Configuration @EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/api1/*").hasAnyRole("USER","ADMIN") .anyRequest().authenticated() .and() .formLogin().permitAll() .and() .logout().permitAll(); http.csrf().disable(); } @Bean public PasswordEncoder passwordEncoder() { return (DelegatingPasswordEncoder) PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @Autowired private DataSource dataSource; @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception{ return super.authenticationManagerBean(); } @Autowired public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication() .dataSource(dataSource).passwordEncoder(passwordEncoder()) .usersByUsernameQuery("select username,password,enabled from users where username=?") .authoritiesByUsernameQuery("select username,authority from authorities where username=?"); } }
Principal in spring security is used to get the details of currently logged in user.package com.codeusingjava.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.security.Principal; @RestController public class HelloController { @GetMapping("/api1") public String Welcome(@RequestParam(required = false,defaultValue = "Welcome User") String name, Principal principal) { return name+" : You are logged in as "+principal.getName()+""; } }
package com.codeusingjava.websecurity; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class WebsecurityApplication { public static void main(String[] args) { SpringApplication.run(WebsecurityApplication.class, args); } }
We login here by the username and password which we inserted in our database. The next page would be shown only by entering correct username and password.
Here we are login by using username and password of User.