Spring Security Complete Guide
Simple & Easy to Understand
TABLE OF CONTENTS
1. What is Spring Security?
2. Key Concepts & Terms
3. Authentication (Login)
4. Authorization (Permissions)
5. Configuration Setup
6. Securing REST APIs
7. Securing Web Applications
8. Common Implementations
9. Best Practices
10. Troubleshooting
1. What is Spring Security?
Spring Security is a powerful framework for securing Java applications. Think of it as a
bodyguard for your app:
• Prevents unauthorized access - Only lets people in who should be allowed
• Protects sensitive data - Keeps passwords and important info safe
• Handles login/logout - Manages user sessions
• Controls permissions - Decides what each user can do
2. Key Concepts & Terms
Principal: A person or entity trying to access your app (usually a user)
Authentication: Verifying WHO you are (username + password login)
Authorization: Checking WHAT you're allowed to do (user roles & permissions)
Security Context: Information about the currently logged-in user
Filter Chain: A series of checks your request passes through before reaching your app
Roles: User groups like ADMIN, USER, MANAGER
Authorities: Individual permissions like READ, WRITE, DELETE
3. Authentication (Login)
Authentication = Proving Who You Are
Process:
1. User enters username and password
2. Spring Security receives the request
3. Checks username against database
4. Compares password hash (not plain text)
5. If match → User is authenticated, session created
6. If no match → Request rejected
Minimum Setup ([Link]):
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
4. Authorization (Permissions)
Authorization = Checking What You Can Do
After authentication, Spring Security checks if user has permission:
• Role-based: User has ADMIN role → can delete posts
• Permission-based: User has WRITE permission → can edit
Example:
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminPanel() { return "Admin Area"; }
5. Configuration Setup
Step 1: Add Dependency
Add spring-boot-starter-security to your [Link] or [Link]
Step 2: Create Security Configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin();
return [Link]();
}
}
6. Securing REST APIs
For APIs, use JWT (JSON Web Tokens)
JWT = A token that proves you're logged in
• User logs in → receives JWT token
• User sends token with each API request
• Server validates token → processes request
Basic API Security Example:
@GetMapping("/api/users")
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
public List<User> getUsers() {
return [Link]();
}
7. Securing Web Applications
For Web Apps, use Form Login or Session-based
Flow:
1. User visits login page
2. Enters credentials and submits
3. Server validates and creates session
4. Browser stores session cookie
5. Each request includes cookie automatically
@GetMapping("/dashboard")
@PreAuthorize("isAuthenticated()")
public String dashboard() {
return "dashboard";
}
8. Common Implementations
A. In-Memory Users (Testing Only)
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = [Link]()
.username("user")
.password("{noop}password")
.roles("USER")
.build();
UserDetails admin = [Link]()
.username("admin")
.password("{noop}admin123")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
B. Database User Authentication
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) {
User user = [Link](username)
.orElseThrow(() -> new RuntimeException("User not found"));
return [Link]()
.username([Link]())
.password([Link]())
.roles([Link]())
.build();
}
}
C. Password Encoding
ALWAYS encode passwords! Never store plain text.
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
9. Best Practices
✓ Always hash passwords using BCrypt or Argon2
✓ Use HTTPS for all requests (encrypt in transit)
✓ Keep tokens short-lived (15-30 minutes)
✓ Refresh tokens should be longer (7 days)
✓ Implement CSRF protection for form submissions
✓ Use strong password requirements
✓ Log security events (failed logins, etc)
✓ Validate and sanitize user input
✓ Use @PreAuthorize instead of checking roles manually
✓ Never trust client-side validation alone
✓ Implement rate limiting for login attempts
✓ Use CORS properly to prevent unauthorized domains
10. Troubleshooting
"Access Denied" error: User doesn't have required role/permission. Check @PreAuthorize
annotation and user's assigned roles.
Endless redirect loop: Login page might be protected. Add .antMatchers("/login").permitAll()
CSRF errors: Disable for APIs (.csrf().disable()) but enable for web forms
Session lost after restart: Normal behavior. Users must login again. Use persistent storage
if needed.
Password not matching: Ensure you're using same encoder for both storing and validating
passwords
QUICK SETUP CHECKLIST
■ Add spring-boot-starter-security dependency
■ Create SecurityConfig class with @Configuration
■ Define what URLs need authentication (.authorizeRequests)
■ Set up login/logout (.formLogin())
■ Create UserDetailsService or use database
■ Implement password encoding (BCrypt)
■ Add @PreAuthorize annotations to protected methods
■ Test with different user roles
■ Enable CSRF protection for web apps
■ Configure CORS if building APIs
Remember: Security is not optional—it's essential!