We have one more tutorial naming Spring Boot 2.x Security using Username Password, if you want to check out that you can have a look. In this tutorial we will be seeing how to do the same with Spring Boot 3.x, which internally uses Spring Security 6.x
Create a Spring boot app using spring inilialzr by adding below dependencies:
- Spring Security
- Web
- H2
- JPA
- Lombok
As we did in Spring Boot 2.x Security tutorial, add a Entity class:
P.S.: In Spring Boot 2.x the Entity and other persistence classes were present in javax.persistence package. But in Spring Boot 3.x the same is present in jakarta.persistence package.
As we did in the Spring Boot 2.x Security using Username Password tutorial, add these classes/interfaces in a similar way – entity, repository, controller and service.
Now lets add our Security Config class. Here there are couple of changes. First change is you don’t have to extend from WebSecurityConfigurerAdapter as we did in Spring Security 2.x, because this class is deprecated. Now the Security Config class don’t have to extend from any class or interface.
And the second change is the methods to override. In 2.x you had overridden 2 methods called –confgure(AuthenticationManagerBuilder) and configure(HttpSecurity), first one was for the authentication and second one for the authorization. Here since you are not extending from any class you can give any name for authentication and authorization. The signature of the same methods is as below for authentication and authorization respectively :
public AuthenticationProvider myAuthenticationProvider()
public SecurityFilterChain mySecurityFilterChain(HttpSecurity httpSecurity)
In the just below code snippet we had only added the authentication method. The authorization method is show after that:
import com.heapsteep.service.MyUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class MySecurityConfig{ @Autowired private MyUserDetailsService myUserDetailsService; @Bean public PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance(); } @Bean public AuthenticationProvider myAuthenticationProvider(){ DaoAuthenticationProvider authenticationProvider=new DaoAuthenticationProvider(); authenticationProvider.setUserDetailsService(myUserDetailsService); authenticationProvider.setPasswordEncoder(passwordEncoder()); return authenticationProvider; } }
Now start the application by doing- gradle bootrun
When you call this url: http://localhost:8080, you will get a popup window asking for your credentials.
Enter the correct credentials and then you will get the below message:
Lets now see how to add Authorization and “Partial-Authentication” stuff. Suppose we want to restrict some urls to be authenticated and some urls not to be authenticated. How to do that ?
Authorization:
Now lets modify the above code to add Authorization to it.
Before your work on the authorization part make sure to modify the User entity class to have the roles column and accordingly update the insert queries in data.sql file.
Then you have to modify your SecurityFilterChain method in your SecurityConfig file to add below line:
.hasAnyAuthority(“ROLE_NAME”)
The complete method is below:
@Bean public SecurityFilterChain mySecurityFilterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity.authorizeHttpRequests((x) -> x .requestMatchers("/api1").hasAnyAuthority("ADMIN") .requestMatchers("/api2").hasAnyAuthority("HR") .requestMatchers("/api3","/api4").authenticated() .requestMatchers("/").permitAll()) .formLogin(Customizer.withDefaults()) .httpBasic(Customizer.withDefaults()); return httpSecurity.build(); }
In the above code we can represent these things:
“/” endpoint can be accessed without any authentication.
“/api3” and “/api4” endpoints has to pass through authentication and it can be accessed by any Role.
“/api2” endpoints can be accessed by HR Role only.
And respectively.
Thats all !.. Now your application is both Authentication and Authorization enabled.
Source code of the above can be found here: https://github.com/heapsteep/spring-security-3-password
P.S:
Starting from Spring Security 6.1 and Spring Boot 3.1.0 versions, the Spring Security framework team recommends using the Lambda DSL style for configuring security for APIs, web paths, etc. Consequently, they have deprecated a few methods within the framework. These deprecated methods are planned to be removed in Spring Security 7, which is expected to be released in the next 2-3 years. This timeframe allows all developers sufficient time for migrating their code.
Below, you will find an example code snippet illustrating the differences between the two styles:
With out Lambda DSL
With Lambda DSL
The Lambda DSL was created to accomplish to following goals:
- Automatic indentation makes the configuration more readable.
- There is no need to chain configuration options using
.and()
- The Spring Security DSL has a similar configuration style to other Spring DSLs such as Spring Integration and Spring Cloud Gateway.