Spring Security
What is Spring Security?
Spring Security is a powerful and highly customizable authentication and access-control framework for Java applications. It is the de-facto standard for securing Spring-based applications. It provides:
- Authentication (who are you?)
- Authorization (what can you do?)
- Protection against common attacks (CSRF, session fixation, clickjacking)
- Integration with OAuth2, JWT, LDAP, and more
package com.example.config;
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// Authorization rules
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/home", "/register", "/css/**", "/js/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/api/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
// Form login
.formLogin(form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/dashboard", true)
.failureUrl("/login?error=true")
.permitAll()
)
// Logout
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll()
)
// HTTP Basic auth (for REST APIs)
// .httpBasic(Customizer.withDefaults())
// CSRF protection (disable for REST APIs)
// .csrf(csrf -> csrf.disable())
;
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12); // Strength 12
}
}
UserDetailsService
package com.example.security;
import com.example.entity.User;
import com.example.repository.UserRepository;
import org.springframework.security.core.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.*;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
// Convert roles to GrantedAuthority
List<GrantedAuthority> authorities = List.of(
new SimpleGrantedAuthority("ROLE_" + user.getRole().name())
);
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(), // BCrypt hashed password
authorities
);
}
}
// Registration service - hash password before saving
@Service
public class RegistrationService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public RegistrationService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
public User register(String username, String email, String rawPassword) {
User user = new User();
user.setUsername(username);
user.setEmail(email);
user.setPassword(passwordEncoder.encode(rawPassword)); // Hash!
user.setRole(User.Role.USER);
return userRepository.save(user);
}
}
Method Security
// Enable method security in config:
// @EnableMethodSecurity(prePostEnabled = true)
@Service
public class AdminService {
// Only ADMIN role can call this
@PreAuthorize("hasRole('ADMIN')")
public List<User> getAllUsers() {
return userRepository.findAll();
}
// User can only access their own data
@PreAuthorize("hasRole('ADMIN') or #username == authentication.name")
public User getUserProfile(String username) {
return userRepository.findByUsername(username).orElseThrow();
}
// Check after method returns
@PostAuthorize("returnObject.username == authentication.name or hasRole('ADMIN')")
public User getUser(Long id) {
return userRepository.findById(id).orElseThrow();
}
// Secure with SpEL expression
@PreAuthorize("hasRole('ADMIN') and #user.role != 'ADMIN'")
public void deleteUser(User user) {
userRepository.delete(user);
}
}
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.