Spring Security part 1 - Configuration
Spring Security is a well made and powerful authentication and authorization framework used for securing Spring-based applications. The underlying value is how quickly and easily it can be configured and extended to meet most business requirements. However, because it’s so configurable it can be daunting to set up and understand how to quickly get it running for your application. This 5 part series will take you through a real-world example from start to finish.
Other Articles
- Architecture - Spring Security Architecture
- Part 1 - Security configuration
- Part 2 - How to handle UserDetails gracefully
- Part 3 - UserDetails for OAuth authentication
- Part 4 - Handling GrantedAuthorities with custom roles/permissions
- Part 5 - Security tags for Freemarker
Prerequistes
This series on Spring Security uses Spring 6
. Enable Spring Security by adding the following dependency into your pom.xml
.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
HomeController
We’re going to need something to secure. Create a simple web controller.
@Controller
public class HomeController {
@GetMapping("/")
public ResponseEntity<String> home(Model model) {
return new ResponseEntity<String>("Hello World", HttpStatus.OK);
}
@GetMapping(value = "/user/view", produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> userTest(Model model) {
return new ResponseEntity<String>("Hello User", HttpStatus.OK);
}
}
Security Configuration
Create a new base class and give it meaningful name. You’ll need to annotate it with @Configuration
so Spring knows this class contains configuration for your application.
You’ll need to annotate it with @EnableWebSecurity
to have the Spring Security configuration defined by exposing a SecurityFilterChain
bean.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
}
Immediately after bringing in the Spring Security dependencies, without any configuration, you’ll notice your web application forward you to a login page for all requests. With a little configuration we can allow some requests to go through without authentication.
When we added @EnableWebSecurity
, it automatically enables CSRF protection. This is activated by default when using EnableWebSecurity’s default constructor. This also populates the CsrfFilter
.
You can disable CSRF with this code:
http.csrf().disable()
Basic configuration
Let’s configure the /
mapping so its avaiable to everyone and configure the /user
mapping so only authenticated users can view it. The authorizeHttpRequests()
method enables the requestMatchers
which allows us to easily configure each mapping. Keep in mind, order will matter here. When a filter matches it will stop processing the remaining ones. If you have requestMatchers("/**")
above the user mapping, it will allow everyone to see both URLs.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers("/user/**").authenticated()
.requestMatchers("/**").permitAll()
.and()
.formLogin();
return http.build();
}
Set up users & in-memory database
To keep things simple we will use an in-memory database and clear text password. In a production environment you’ll want to use a PasswordEncoder that encrypts the password.
@Bean
public static PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Bean
public UserDetailsService users() {
UserDetails user = User.builder()
.username("user")
.password("user")
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password("admin")
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin, user2);
}
Comments
Post a Comment