Spring Security Implementation With Basic Auth
In this article, we will explore the implementation of Spring Security, a powerful framework that provides robust authentication and authorization mechanisms for Java applications. We will cover various aspects of Spring Security, from its advantages and adding dependencies to configuring different authentication methods. By the end of this guide, you will have a clear understanding of how to implement Spring Security in your projects.
Table of Contents:
- Why Spring Security?
- Adding Dependencies
- Create SecurityConfig Class & Configure Basic Auth
- Configuring For In-Memory User Authentication
- Configuring for Real-Time Database Users
Why Spring Security?
Spring Security offers numerous advantages that make it a preferred choice for securing Java applications. It enhances application security by providing robust protection against common vulnerabilities. Spring Security simplifies the process of adding security features to your application. It supports a wide range of authentication mechanisms, allowing you to choose the most suitable method for your project. Additionally, It provides customizable access control, giving you fine-grained control over user permissions and roles. These advantages collectively make Spring Security a reliable and flexible framework for implementing robust authentication and authorization in your Java applications.
Adding Dependency For Spring Security
Before implementing Spring Security, you need to add the necessary dependencies to your project. Here’s an example using Maven:
In your project’s pom.xml file, add the following dependencies within the <dependencies> section:
<dependencies>
<!-- Other dependencies -->
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Additional dependencies based on your project requirements -->
</dependencies>xNote: It’s crucial to ensure compatibility between the Spring Security version and your Spring application’s version. Be mindful of any potential conflicts or incompatibilities when selecting the appropriate dependencies.
Create a SecurityConfig Class
Create a new Java class named SecurityConfig in your project's source code directory.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception{
httpSecurity.csrf().disable()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
return httpSecurity.build();
}
}Note : If you want to configure specific url to have permission to anyone or based on specific Role, then, for that we can use requestMatchers to configure. Here is an example where we permit all to signUp for our service.
.authorizeHttpRequests()
.requestMatchers(”/users/signUp”).permitAll()
After this, run your project and you should get a temporary generated password in the logs like this :
Now when you hit your project url, you will be prompted to enter username and password like this, or you can add in Postman Authorization. Here username will be by default `user` and password will be the one generated in the logs.
Configuring In-Memory User Authentication
Get Mohd Aamir’s stories in your inbox
Join Medium for free to get updates from this writer.
Open the SecurityConfig class created earlier.
Modify the class to include a bean for the UserDetailsService that configures an in-memory user with a specific username, password or role.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception{
httpSecurity.csrf().disable()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
return httpSecurity.build();
}
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("aamir")
.password("123")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user);
}
}- In the
SecurityConfigclass, a new methoduserDetailsService()is added and annotated with@Bean. This method configures an in-memory user using theInMemoryUserDetailsManager. - The
UserDetailsobject is created using theUser.builder()method and specifying the desired username, password, and roles. - In this example, the username is set to “aamir” and the password to “123” with the role “ADMIN”.
- The
InMemoryUserDetailsManageris instantiated with the createdUserDetailsobject. - By configuring the
UserDetailsServicebean with an in-memory user, you can authenticate and authorize users using the provided username and password.
These changes ensure that the application now uses the specified username and password for authentication instead of generating a random temporary password. You can modify the username, password, and role according to your requirements.
Now, we have successfully setup spring security using basic auth for a user. Now we can access the Server using these credentials instead of using temporary generated password. Here is a snapshot of that :
Configuring For Real Time Database Users
Now, the last step in setting up spring security using basic Auth, is doing the same using real time database users, instead of an in-memory user.
- Implement the necessary components to interact with the user database, including the
UserDetailsmodel, service, repository, and controller. These components will handle user authentication and authorization. - In the user service, implement the
UserDetailsServiceinterface and its methodloadUserByUsername. This method retrieves the user details from the database, builds aUserDetailsobject from the retrieved information, and returns it. Here's an example:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserDetailsRepository userDetailsRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = userDetailsRepository.findUserByUsername(username);
if (userDetails == null) {
throw new UsernameNotFoundException("User with username: " + username + " not found");
}
// Create and return the Spring Security UserDetails object
return org.springframework.security.core.userdetails.User.builder()
.username(userDetails.getUsername())
.password(userDetails.getPassword())
.roles("ADMIN") // Replace with appropriate roles from userDetails if available
.build();
}
}Update the SecurityConfig class by removing the in-memory user configuration, autowiring the UserDetailsServiceImpl class, and making other necessary changes. Here's an example:
@Configuration
public class SecurityConfig {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
authenticationManager = authenticationManagerBuilder.build();
httpSecurity.csrf().disable()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.authenticationManager(authenticationManager)
.httpBasic();
return httpSecurity.build();
}
}Now, while making request, you just need to add real username and password, it will encode the password, then match the password in your database for that username, if matches, user will be authorised.
Note :- In your user service, while you are creating new user, ensure that you are saving the password after encoding it properly. Here is an example in reference to above config :
public void addUserDetails(UserDetails userDetails){
String encodedPassword = new BCryptPasswordEncoder().encode(userDetails.getPassword());
userDetails.setPassword(encodedPassword);
userDetailsRepository.save(userDetails);
}Spring Security’s basic authentication is a simple and straightforward method for authenticating users by sending their credentials (username and password) with each request. However, it has some limitations in terms of usefulness and security.
Hence, there are other securer methods of authorization like JWT, which i am planning to cover step by step in another article.
If you have any questions or topics you’d like me to cover in future articles, please feel free to reach out. Happy coding!






