Spring: Spring Security
Security Configuration (Spring Security 6)
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable()) // stateless JWT API
.sessionManagement(sm -> sm
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(ex -> ex
.authenticationEntryPoint((req, res, e) ->
res.sendError(401, "Unauthorized"))
.accessDeniedHandler((req, res, e) ->
res.sendError(403, "Forbidden")))
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Bean
public AuthenticationManager authManager(UserDetailsService uds) {
var provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(uds);
provider.setPasswordEncoder(passwordEncoder());
return new ProviderManager(provider);
}
}JWT Filter
@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
var authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
chain.doFilter(request, response);
return;
}
var token = authHeader.substring(7);
var username = jwtService.extractUsername(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
var userDetails = userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(token, userDetails)) {
var auth = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
chain.doFilter(request, response);
}
}UserDetailsService & Method Security
// UserDetailsService — loads user from DB for authentication
@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return userRepository.findByEmail(email)
.map(user -> org.springframework.security.core.userdetails.User
.withUsername(user.getEmail())
.password(user.getPassword())
.roles(user.getRole().name()) // ROLE_ prefix added automatically
.accountLocked(!user.isActive())
.build())
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + email));
}
}
// Method-level security (requires @EnableMethodSecurity)
@RestController
public class AdminController {
@GetMapping("/api/admin/users")
@PreAuthorize("hasRole('ADMIN')") // annotation-based
public List<User> getAllUsers() { }
@PutMapping("/api/users/{id}")
@PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id")
public User updateUser(@PathVariable Long id, @RequestBody UpdateUserRequest req) { }
@DeleteMapping("/api/posts/{id}")
@PreAuthorize("@postService.isOwner(#id, authentication.name)") // SpEL with bean
public void deletePost(@PathVariable Long id) { }
}
// Get current user anywhere
public User getCurrentUser() {
var auth = SecurityContextHolder.getContext().getAuthentication();
return (User) auth.getPrincipal();
}Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free