Spring Security
About 3 minNoteFrameworkSpringBackend
OWASP Top 10 Web Application Security Risks (2021)
- Broken Access Control
- Cryptographic Failures
- Injection
- Insecure Design
- Security Misconfiguration
- Vulnerable and Outdated Components
- Identification and Authentication Failures
- Software and Data Integrity Failures
- Security Logging and Monitoring Failures
- Server-side Request Forgery
Spring Security
- Security filter chain

- Adding a custom filter
SecurityContextis loaded from the session- Request is protected from common exploits; secure headers, CORS, CSRF
- Request is authenticated
- Request is authorized
- What Spring Boot enables in Spring Security by default
- Requires an authenticated user for any endpoint (including Boot’s
/errorendpoint) - Registers a default user with a generated password at startup (the password is logged to the console; in the preceding example, the password is
8e557245-73e2-4286-969a-ff57fe326336) - Protects password storage with BCrypt as well as others
- Provides form-based login and logout flows
- Authenticates form-based login as well as HTTP Basic
- Provides content negotiation; for web requests, redirects to the login page; for service requests, returns a
401 Unauthorized - Mitigates CSRF attacks
- Mitigates Session Fixation attacks
- Writes Strict-Transport-Security to ensure HTTPS
- Writes X-Content-Type-Options to mitigate sniffing attacks
- Writes Cache Control headers that protect authenticated resources
- Writes X-Frame-Options to mitigate Clickjacking
- Integrates with
HttpServletRequest's authentication methods - Publishes authentication success and failure events
- Requires an authenticated user for any endpoint (including Boot’s
CSRF
- Cross-Site Request Forgery
- An attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated
- For most sites, browser requests automatically include any credentials associated with the site, such as the user’s session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the victim and a legitimate request sent by the victim
- Solution one: CSRF token
- Everytime you send a request which is not a GET request, you have to send a CSRF token with the request
- Solution two: Stateless API
- EVerytime you send a request, you have to send username and password with it, there is no session then
Authentication Mechanisms
Username and Password
Password storage
In memory
package com.hadjshell.springsecdemo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { // Custom security filter chain @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(customizer -> customizer.disable()) .authorizeHttpRequests(request -> request.anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); return http.build(); } @Bean public UserDetailsService userDetailsService() { UserDetails user = User // this method is deprecated .withDefaultPasswordEncoder() // encrypt password .username("navin") .password("n@123") .roles("USER") .build(); UserDetails admin = User .withDefaultPasswordEncoder() .username("admin") .password("admin@789") .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(user,admin); } }
In database
package com.telusko.springsecdemo.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import com.hadjshell.springsecdemo.repo.UserRepo; import com.hadjshell.springsecdemo.model.User; import com.hadjshell.springsecdemo.model.UserPrincipal; @Service public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepo repo; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user= repo.findByUsername(username); if (user==null) { System.out.println("User 404"); throw new UsernameNotFoundException("User 404"); } return new UserPrincipal(user); } }package com.hadjshell.springsecdemo.model; import java.util.Collection; import java.util.Collections; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; public class UserPrincipal implements UserDetails{ private static final long serialVersionUID = 1L; private User user; public UserPrincipal(User user) { this.user = user; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return Collections.singleton(new SimpleGrantedAuthority("USER")); } @Override public String getPassword() { return user.getPassword(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }@Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private UserDetailsService userDetailsService; @Bean public AuthenticationProvider authProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); return provider; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(customizer -> customizer.disable()) .authorizeHttpRequests(request -> request.anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); return http.build(); } }
In LDAP
Encrypt password
OAuth 2.0 Login
Remember Me
