Spring Security is a powerful and highly customizable authentication and access-control framework for Java applications. Whether you are building a small application or a large enterprise system, securing your application is paramount. In this article, we’ll explore how to get started with Spring Security, focusing specifically on username and password authentication.
What is Spring Security?
Spring Security is a part of the larger Spring Framework, which provides a comprehensive set of tools for building secure applications. It offers a wide range of features, including:
- Authentication and authorization
- Comprehensive and extensible support for both programmatic and declarative security
- Protection against common vulnerabilities such as session fixation, clickjacking, cross-site request forgery, and more
- Integration with many authentication mechanisms, including LDAP, OAuth, and OpenID Connect
Setting Up Your Project
To get started, you’ll need to set up a Spring Boot project. If you haven’t already, you can create a new Spring Boot project using the Spring Initializr (https://start.spring.io/). Select the following dependencies:
- Spring Web
- Spring Security
Once you have your project set up, open the pom.xml
file (or build.gradle
if you’re using Gradle) to ensure the necessary dependencies are included:
<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>
Basic Configuration
Spring Security provides a default configuration that requires all users to be authenticated. However, to customize the authentication process, you need to create a configuration class.
Create a new class named SecurityConfig
:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
In this configuration:
- We permit access to all URLs under
/public/**
without authentication. - All other requests require authentication.
- We configure form-based login with a custom login page at
/login
. - We enable logout support.
Creating a User Service
To manage users, you’ll need to create a service that implements UserDetailsService
. This service will load user-specific data.
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private Map<String, User> users = new HashMap<>();
public CustomUserDetailsService() {
// Add a default user for testing purposes
users.put("user", new User("user", "$2a$10$D9QNOI0G6NFAiT6TtBFR9u8PPQeOdXvWyxr9uYx6uwDhDfE8p5u.a", "ROLE_USER")); // password: password
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = users.get(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return user;
}
}
In this example, a default user with the username “user” and password “password” is created. The password is encoded using BCrypt.
Custom Login Page
Create a custom login page named login.html
in the src/main/resources/templates
directory:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<form th:action="@{/login}" method="post">
<div>
<label>Username:</label>
<input type="text" name="username"/>
</div>
<div>
<label>Password:</label>
<input type="password" name="password"/>
</div>
<div>
<button type="submit">Login</button>
</div>
</form>
</body>
</html>
Running the Application
Now that everything is set up, you can run your Spring Boot application. Navigate to http://localhost:8080/login
to see your custom login page. Use the username “user” and the password “password” to log in.
Conclusion
Spring Security makes it easy to secure your applications with robust authentication and authorization mechanisms. In this article, we’ve covered the basics of setting up username and password authentication in a Spring Boot application. From here, you can explore more advanced features of Spring Security, such as integrating with external authentication providers, implementing role-based access control, and securing RESTful APIs.
By following these steps, you can ensure that your Spring Boot application is secure and ready to handle user authentication with ease.