Spring Security is a robust framework for securing Java-based applications. It provides mechanisms for authentication, authorization, and protection against common vulnerabilities.
1. Core Concepts of Spring Security
- Authentication: Verifies the identity of a user or system.
- Authorization: Determines access permissions based on roles or attributes.
- Filter Chain: A sequence of filters that intercept requests for security purposes.
- SecurityContext: Stores authentication and security-related information.
- Principal: Represents the currently authenticated user.
2. Principles of Spring Security
- Separation of Concerns: Decouples security logic from application logic.
- Declarative Security: Provides configuration through annotations or XML.
- Pluggability: Supports integration with custom authentication providers (e.g., OAuth2, LDAP).
- Defense in Depth: Combines multiple layers of security.
3. Ways to Implement Security in Spring Boot
3.1. Basic Authentication
Protects endpoints using HTTP Basic Authentication.
Steps to Implement Basic Authentication:
- Add Spring Security dependency in
pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- Configure the security filter chain:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.httpBasic();
return http.build();
}
}
- Define default credentials in
application.properties:
spring.security.user.name=admin spring.security.user.password=admin123
3.2. Form-Based Authentication
Presents a custom login form for user authentication.
Steps to Implement Form-Based Authentication:
- Configure form login in the security filter chain:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
return http.build();
}
}
- Create a custom login page:
<!-- src/main/resources/templates/login.html -->
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" name="username" id="username">
<label for="password">Password:</label>
<input type="password" name="password" id="password">
<button type="submit">Login</button>
</form>
3.3. Role-Based Authorization
Restricts access to specific endpoints based on user roles.
Steps to Implement Role-Based Authorization:
- Define role-based access in the security filter chain:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.httpBasic();
return http.build();
}
}
- Configure in-memory users with roles:
@Bean
public UserDetailsService userDetailsService() {
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("admin123")
.roles("ADMIN")
.build();
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("user123")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(admin, user);
}
3.4. OAuth2 Authentication
Enables third-party login using providers like Google or GitHub.
Steps to Implement OAuth2:
- Add OAuth2 dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
- Configure OAuth2 in
application.properties:
spring.security.oauth2.client.registration.google.client-id=your-client-id spring.security.oauth2.client.registration.google.client-secret=your-client-secret spring.security.oauth2.client.registration.google.scope=email,profile
- Enable OAuth2 login:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.oauth2Login();
return http.build();
}
}
JWT Structure
php-templateCopyEdit<Header>.<Payload>.<Signature>
Each part is Base64Url-encoded and separated by dots (.).
1️⃣ Header
Describes the token type and signing algorithm.
Example (before encoding):
{
"alg": "HS256",
"typ": "JWT"
}
alg= algorithm (e.g.,HS256,RS256)typ= token type (JWT)
2️⃣ Payload (Claims)
Contains the actual data or claims (like user ID, roles, expiry time, etc.).
Example:
{
"sub": "1234567890",
"name": "John Doe",
"role": "admin",
"exp": 1712345678
}
Some standard claims:
sub– subject (usually user ID)iat– issued at timestampexp– expiration timestampaud,iss,nbf,jti– other standard claims- You can also add custom fields like
role,email, etc.
3️⃣ Signature
Ensures the token wasn’t tampered with. It’s calculated using:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
If the signature is invalid, the token is considered compromised.
🧪 Sample JWT (Base64 Encoded)
CopyEditeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNzEyMzQ1Njc4fQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
🔐 Summary
| Part | Purpose |
|---|---|
| Header | Algorithm & token type |
| Payload | Claims/data (public info) |
| Signature | Verifies authenticity & integrity |
4. JWT Authentication
Stateless authentication using JSON Web Tokens.
Steps to Implement JWT Authentication:
- Add JWT dependency:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
- Create a JWT utility class:
@Component
public class JwtUtil {
private final String secret = "my-secret-key";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(Keys.hmacShaKeyFor(secret.getBytes()), SignatureAlgorithm.HS256)
.compact();
}
public String extractUsername(String token) {
return Jwts.parserBuilder()
.setSigningKey(secret.getBytes())
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
5. Annotations and Configuration in Main Spring Boot File
- Annotate the main class with
@SpringBootApplication:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- Use
@EnableWebSecurityin the Security Configuration class to enable Spring Security:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
// Security configurations
}
6. Best Practices
- Always use HTTPS to secure data transmission.
- Define strong password policies and enforce them.
- Use security headers to protect against common attacks.
- Log authentication and authorization events.
- Write integration tests to validate security configurations.
This document covers multiple security approaches in Spring Boot with examples and explanations. Let me know if you’d like to explore any specific use case further!