In this tutorial we would make our Spring Boot application secure using username and password. That means every time you wanna access any API you have to enter the credentials. This type of application is not recommended but we wanted you to show the Spring Security file structure.
Then the next step would be to add JWT library to make it JWT enabled.
Lets proceed with creating a spring boot app by adding below dependencies:
- Web
- Security
- JPA
- H2
- Lombok
We will name this app as “spring-security-password“, and we will use Gradle as the build tool and H2 as the DB.
The build.gradle will have below dependencies:
dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' }
The application.properties:
spring.h2.console.enabled=true spring.datasource.url=jdbc:h2:mem:testdb spring.data.jpa.repositories.bootstrap-mode=default spring.jpa.defer-datasource-initialization=true
Below is the Entity class – User.java, which will create the SEC_USER table automatically in the DB once we run the application.
@Data @AllArgsConstructor @NoArgsConstructor @Entity @Table(name = "SEC_USER") public class User { @Id private int id; private String userName; private String password; }
Add the below content to data.sql file in /resources folder. This will insert the dummy user credentials to the database once the application is started:
insert into sec_user(id, user_name, password) values(1,'Prasanna','1234'); insert into sec_user(id, user_name, password) values(2,'Padma','1234'); insert into sec_user(id, user_name, password) values(3,'Sarojini','1234');
Lets add a controller class – MyController.java where we will add a endpoint:
@RestController public class MyController { @GetMapping("/") public String welcome() { return "Welcome to Heapsteep !!"; } }
Add a repository class which will fetch the user details from the DB:
public interface UserRepository extends JpaRepository<User,Integer> { User findByUserName(String username); }
Now, the very important two classes that we have to write. This is what I wanted to show you guys, the Spring Security file structure and flow. We will be using the same structure while adding JWT functionality to it.
Create your service class – MyUserDetailsService.java by implementing from UserDetailsService interface of Spring Security framework and override the loadUserByUsername() method:
import com.heapsteep.entity.User; import com.heapsteep.repository.UserRepository; import org.springframework.security.core.userdetails.UserDetailsService; @Service public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository repository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = repository.findByUserName(username); return new org.springframework.security.core.userdetails.User (user.getUserName(), user.getPassword(), new ArrayList<>()); } }
In the above example the return type is UserDetails, since its a interface so we had created a User class of Spring Security framework, which internally implements UserDetails interface, and we are returning this object.
Then, create a security config class- MySecurityConfig.java by extending from Spring Security’s WebSecurityConfigurerAdapter class.
import com.heapsteep.service.MyUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class MySecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyUserDetailsService myUserDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(myUserDetailsService); } @Bean public PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance(); } }
In the above class make sure to add the below annotations:
@Configuration
@EnableWebSecurity
And, if you are using Spring Boot 2.X or above version, don’t forget to add the spring boot password encoder bean in the above class.
Now start the application by doing- gradle bootrun
When you call this url: http://localhost:8080, you will get a popup window asking for your credentials.
Enter the correct credentials and then you will get the below message:
Source code can be found here: https://github.com/heapsteep/spring-security-password