Using Spring Security for authentication and authorization

This web application has used Spring Security for authentication of users and to authorize them to submit comments. The Maven Spring Security starter needs to be specified, as follows, to enable Spring Security in the web application:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-webflux</artifactId>
<version>5.0.0.M2</version>
</dependency>
</dependencies>

The following is the Spring Security configuration:

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {

@Autowired
private UserService userService;

@Bean
public SecurityWebFilterChain
springWebFilterChain(ServerHttpSecurity http) throws Exception {
return http
.authorizeExchange().pathMatchers(HttpMethod.GET,
"/article", "/article/show/**", "/webjars/**", "/css/**",
"/favicon.ico",
"/").permitAll()
.pathMatchers(HttpMethod.POST,
"/article").authenticated()
.pathMatchers("/article/edit/**", "/article/new",
"/article/delete/**").authenticated()
.and()
.csrf().disable()
.formLogin()
.and()
.logout()
.and()
.build();
}

Since the Bloggest application makes use of Spring WebFlux, it also needs to use Reactive Spring Security. This is a new feature introduced in conjunction with Spring Framework 5.0 and Spring WebFlux, so the code may look unfamiliar. The preceding SecurityConfig configuration class does the following.

With the @EnableWebFluxSecurity annotation, Spring WebFlux controller security is enabled. This will enable us to protect the URLs of the Bloggest application. Also, it has @EnableReactiveMethodSecurity, where the @Secured annotation can be used on top of methods to be protected. 

The springWebFilterChain(ServerHttpSecurity http) method, which uses the parameter http passed into configure and build SpringWebFilterChain, will be used to protect endpoints in the Bloggest application:

    @Bean
public UserDetailsRepositoryReactiveAuthenticationManager
authenticationManager(BlogReactiveUserDetailsService
blogReactiveUserDetailsService) {
UserDetailsRepositoryReactiveAuthenticationManager
userDetailsRepositoryReactiveAuthenticationManager = new
UserDetailsRepositoryReactiveAuthenticationManager
(blogReactiveUserDetailsService);
userDetailsRepositoryReactiveAuthenticationManager.
setPasswordEncoder(passwordEncoder());
return userDetailsRepositoryReactiveAuthenticationManager;
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Furthermore, the method authenticationManager returns UserDetailsRepositoryReactiveAuthenticationManagerwhich is configured to have the following ReactiveUserDetailsService implementation to load instances of  User by username using UserRepository:

@Service
public class BlogReactiveUserDetailsService implements ReactiveUserDetailsService {

private final UserRepository userRepository;

public BlogReactiveUserDetailsService(UserRepository
userRepository) {
this.userRepository = userRepository;
}

@Override
public Mono<UserDetails> findByUsername(String s) {
User user = userRepository.findByUsername(s);
if (user == null) {
return Mono.empty();
}
return Mono.just(new
org.springframework.security.core.userdetails.User
(user.getUsername(), user.getPassword(), Arrays.asList(new
SimpleGrantedAuthority(user.getRole()))));
}
}

The preceding implementation finds a User by username, encapsulates the inside of UserDetails and returns it as Mono (UserDetails encapsulated inside of a Mono object). Also, configure the passwordEncoder to be used as follows:

    @Bean
public ApplicationRunner applicationRunner() {
return args -> {
userService.deleteAll();
userService.save(new User(UUID.randomUUID().toString(),
"user", passwordEncoder().encode("password"), "USER",
"User of Blog"));
userService.save(new User(UUID.randomUUID().toString(),
"admin", passwordEncoder().encode("password"), "ADMIN",
"Admin of Blog"));
};
}

}

The method applicationRunner() is used to create and return an ApplicationRunner instance to clear the existing users from the Elasticsearch data store and create some Users.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.244.228