Spring Security

Language: Java

Security

Spring Security was created to provide a comprehensive security solution for Java applications, seamlessly integrating with the Spring ecosystem. It supports features like authentication, authorization, password encoding, CSRF protection, session management, and more.

Spring Security is a powerful and highly customizable framework for authentication, authorization, and protection against common security threats in Java applications.

Installation

maven: Add spring-boot-starter-security dependency in pom.xml
gradle: Add implementation 'org.springframework.boot:spring-boot-starter-security' in build.gradle

Usage

Spring Security allows developers to secure web applications and APIs by managing authentication and authorization. It provides out-of-the-box security filters, supports custom user services, and integrates with OAuth2, JWT, LDAP, and more.

Securing all endpoints with HTTP Basic

// SecurityConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .httpBasic();
    }
}

This configuration secures all endpoints and uses HTTP Basic authentication.

Creating an in-memory user

// SecurityConfig.java snippet
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user")
        .password("{noop}password") // {noop} for plain text
        .roles("USER");
}

Defines a simple in-memory user with username, password, and role.

Securing endpoints with roles

// SecurityConfig.java snippet
http.authorizeRequests()
    .antMatchers("/admin/**").hasRole("ADMIN")
    .antMatchers("/user/**").hasAnyRole("USER","ADMIN")
    .anyRequest().authenticated();

Restricts access to specific endpoints based on user roles.

Using JWT for stateless authentication

// JWTFilter.java snippet
public class JWTFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
        String token = extractToken(request);
        // validate and set authentication
        filterChain.doFilter(request, response);
    }
}

Illustrates a custom filter to authenticate requests using JWT tokens.

Custom UserDetailsService

import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) {
        // fetch user from DB and return UserDetails object
    }
}

Allows authentication against a database or external source by implementing `UserDetailsService`.

Error Handling

AccessDeniedException: Occurs when a user tries to access a resource without sufficient permissions. Check roles and authorities.
BadCredentialsException: Thrown when authentication fails due to invalid username or password. Ensure correct credentials are provided.
AuthenticationCredentialsNotFoundException: Occurs when no authentication is present in the security context. Ensure security filters are configured correctly.

Best Practices

Never store plain-text passwords; use encoders like BCryptPasswordEncoder.

Use method-level security annotations (`@PreAuthorize`, `@Secured`) for fine-grained control.

Externalize security configurations using properties or profiles.

Monitor failed login attempts and implement account lockout policies.

Leverage OAuth2 or JWT for stateless authentication in APIs.