Java Notes
Complete guide to Spring Security - authentication, authorization, security filter chain, role-based access control, password encoding, and security configuration.
What is Spring Security?
Spring Security is a powerful framework for securing Spring applications. It provides authentication (who are you?), authorization (what can you do?), and protection against common attacks (CSRF, XSS, session fixation).
Security Filter Chain
Basic Security Configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // Disable for REST APIs
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/users/**").hasAnyRole("USER", "ADMIN")
.requestMatchers(HttpMethod.DELETE, "/api/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
}UserDetailsService Implementation
@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + email));
return org.springframework.security.core.userdetails.User.builder()
.username(user.getEmail())
.password(user.getPassword()) // Already BCrypt encoded
.roles(user.getRole().name()) // "USER", "ADMIN"
.accountLocked(!user.isActive())
.build();
}
}Registration and Login
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authManager;
@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody @Valid RegisterRequest request) {
if (userRepository.existsByEmail(request.getEmail())) {
return ResponseEntity.badRequest().body("Email already registered");
}
User user = User.builder()
.name(request.getName())
.email(request.getEmail())
.password(passwordEncoder.encode(request.getPassword()))
.role(Role.USER)
.active(true)
.build();
userRepository.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body("User registered successfully");
}
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
try {
Authentication auth = authManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getEmail(), request.getPassword()));
// Authentication successful
return ResponseEntity.ok("Login successful");
} catch (AuthenticationException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
}
}
}Method-Level Security
@Configuration
@EnableMethodSecurity
public class MethodSecurityConfig { }
@Service
public class UserService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { }
@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
public User getUser(Long userId) { }
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")
public List<User> getAllUsers() { }
@PostAuthorize("returnObject.email == authentication.name")
public User getMyProfile() { }
}Role-Based Access Control
// User entity with role
@Entity
public class User {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
private String password;
@Enumerated(EnumType.STRING)
private Role role;
}
public enum Role {
USER, ADMIN, MANAGER
}Getting Authenticated User
@RestController
@RequestMapping("/api/profile")
public class ProfileController {
@GetMapping
public ResponseEntity<?> getProfile(Authentication authentication) {
String email = authentication.getName();
// OR
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
return ResponseEntity.ok(Map.of(
"email", email,
"roles", authorities.stream()
.map(GrantedAuthority::getAuthority)
.toList()
));
}
// Or using @AuthenticationPrincipal
@GetMapping("/v2")
public ResponseEntity<?> getProfileV2(@AuthenticationPrincipal UserDetails user) {
return ResponseEntity.ok(user.getUsername());
}
}Interview Key Points
- Spring Security uses a filter chain (not interceptors)
- Authentication = identity verification; Authorization = permission checking
SecurityFilterChainbean configures HTTP securityPasswordEncoder(BCrypt) for secure password storageUserDetailsServiceloads user data for authentication@PreAuthorize/@PostAuthorizefor method-level security- CSRF should be disabled for stateless REST APIs
SessionCreationPolicy.STATELESSfor JWT-based auth
Summary
In this chapter, we learned about Spring Security in detail. Here are the key points:
- Basic introduction to the concept and why it is needed
- Syntax and structure with complete examples
- Internal working and best practices
- Real-world applications and use cases
- Common mistakes and how to avoid them
- How this topic is asked in interviews
To practice these concepts, write and run the code in your IDE and verify the output. Modify each example and experiment so that you deeply understand the concept.
Common Security Vulnerabilities and Prevention
Spring Security helps prevent several common web vulnerabilities. Understanding these threats is essential for building secure applications:
Cross-Site Request Forgery (CSRF): CSRF attacks trick authenticated users into performing unintended actions. For traditional web apps with sessions, Spring Security enables CSRF protection by default, generating tokens that must accompany state-changing requests. For stateless REST APIs using JWT tokens, CSRF protection is typically disabled since the token itself provides request authenticity.
Cross-Site Scripting (XSS): While primarily a frontend concern, Spring Security adds response headers like X-Content-Type-Options: nosniff and X-XSS-Protection to mitigate XSS attacks. Always validate and sanitize user input on the server side as well.
Session Fixation: Spring Security automatically creates a new session after login, invalidating any pre-authentication session ID. This prevents attackers from setting a known session ID before the victim logs in.
JWT Token Implementation Details
When implementing JWT-based authentication, consider these production best practices:
- Token expiration: Access tokens should expire in 15-30 minutes. Use refresh tokens (longer-lived) to obtain new access tokens without re-authentication.
- Token storage: Store tokens in httpOnly cookies (not localStorage) to prevent XSS theft.
- Token revocation: Maintain a blacklist of revoked tokens or use short expiration with refresh token rotation.
- Claims design: Include only necessary claims (userId, roles). Avoid sensitive data since JWT payload is base64-encoded, not encrypted.
Testing Spring Security
Testing secured endpoints requires special configuration:
@SpringBootTest
@AutoConfigureMockMvc
class SecurityTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(roles = "ADMIN")
void adminEndpoint_withAdminRole_returns200() throws Exception {
mockMvc.perform(get("/api/admin/dashboard"))
.andExpect(status().isOk());
}
@Test
void protectedEndpoint_withoutAuth_returns401() throws Exception {
mockMvc.perform(get("/api/profile"))
.andExpect(status().isUnauthorized());
}
}The @WithMockUser annotation creates a mock authenticated user for testing, eliminating the need to perform actual login flows in unit tests. For integration tests that verify the full authentication pipeline, use MockMvc with actual credentials.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Spring Security.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, spring, framework, boot
Related Java Master Course Topics