2.1 Starting with the first project
the dependencies you need to write
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
create Hello-Controller
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello!";
}
}
run the application, besides the other lines in the console, you should see:
- call the endpoint
- without using Authorization header:
- using Authorization header:
2.2 Which are the default configurations?
In the following text, will discuss these autoconfigured beans:
- UserDetailsService
- PasswordEncoder
The authentication provider uses these beans to find users and to check their passwords.
2.3 Overriding default configurations
The configuration class for the UserDetailsService bean
@Configuration
public class ProjectConfig {
@Bean
public UserDetailsService userDetailsService() {
var userDetailsService = new InMemoryUserDetailsManager();
return userDetailsService;
}
}
Creating a user with the User builder class for UserDetailsService ```java @Configuration public class ProjectConfig{
@Override @Bean public UserDetailsService userDetailsService() {
var userDetailsService = new InMemoryUserDetailsManager();
var user = User.withUsername("john")
.password("12345")
.authorities("read")
.build();
userDetailsService.createUser(user);
return userDetailsService;
}
}
3. add a PasswordEncoder bean in the context
```java
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
- call the endpoint
\
Extending WebSecurityConfigurerAdapter ```java @Configuration public class ProjectConfig extends WebSecurityConfigurerAdapter { …
@Override protected void configure(HttpSecurity http) throws Exception {
//...
}
}
6. Using the HttpSecurity parameter to alter the configuration
```java
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
//...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests().anyRequest().authenticated();
}
}
The code configures endpoint authorization with the same behavior as the default one. You can call the endpoint again to see that it behaves the same as in the previous one. With a slight change, you can make all the endpoints accessible without the need for credentials.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests().anyRequest().permitAll();
}
2.3.3 Setting the configuration in different ways
Setting UserDetailsService and PasswordEncoder in configure()
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
var userDetailsService = new InMemoryUserDetailsManager();
var user = User.withUsername("john")
.password("12345")
.authorities("read")
.build();
userDetailsService.createUser(user);
auth.userDetailsService(userDetailsService)
.passwordEncoder(NoOpPasswordEncoder.getInstance());
}
}
- Configuring in-memory user management
this approach is not recommend.@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("john")
.password("12345")
.authorities("read")
.and()
.passwordEncoder(NoOpPasswordEncoder.getInstance());
}
2.3.4 Overrding the AuthenticationProvider implementation
It’s time to learn that you can also customize the component that delegates to these, the AuthenticationProvider
Implementing the AuthenticationProvider interface
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//...
}
@Override
public boolean supports(Class<?> authenticationType) {
//...
}
}
Implementing the authenticating logic
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = String.valueOf(authentication.getCredentials());
if ("john".equals(username) && "12345".equals(password)) {
return new UsernamePasswordAuthenticationToken(username, password, Arrays.asList());
} else {
throw new AuthenticationCredentialsNotFoundException("Error!");
}
}
The full implementation of the authentication provider ```java @Component public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = String.valueOf(authentication.getCredentials());
if ("john".equals(username) && "12345".equals(password)) {
return new UsernamePasswordAuthenticationToken(username, password, Arrays.asList());
} else {
throw new AuthenticationCredentialsNotFoundException("Error!");
}
}
@Override public boolean supports(Class<?> authenticationType) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authenticationType);
} }
4. Registering the new implementation of AuthenticationProvider
```java
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider authenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests()
.anyRequest().authenticated();
}
}
2.3.5 Using multiple configuration classes in your project
Defining the configuration class for user and password management
@Configuration
public class UserManagementConfig {
@Bean
public UserDetailsService userDetailsService() {
var userDetailsService = new InMemoryUserDetailsManager();
var user = User.withUsername("john")
.password("12345")
.authorities("read")
.build();
userDetailsService.createUser(user);
return userDetailsService;
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
Defining the configuration class for authorization management
@Configuration
public class WebAuthorizationConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests().anyRequest().authenticated();
}
}