Securing the Place Reviewer backend

Similar to how we went about securing the Messenger API in Chapter 4Designing and Implementing the Messenger Backend with Spring Boot 2.0, we shall utilize Spring Security to secure the Place Reviewer backend. Regardless of the utilization of Spring Security here, there is a slight variation to the way we are going to go about securing our application. In Chapter 4, Designing and Implementing the Messenger Backend with Spring Boot 2.0, we configured Spring Security to rely explicitly on JSON web tokens for the authorization of client applications. This time, we will rely solely on the power of Spring Security. In doing so, we will not make use of any other technology, such as JSON web tokens. Without further ado, let us begin work on securing our backend.

First and foremost, we must create a custom web security configuration for our application. This custom configuration will implement Spring Framework's  WebSecurityConfigurerAdapter. Create a config package in com.example.placereviewer and add the following WebSecurityConfig class:

package com.example.placereviewer.config

import com.example.placereviewer.service.AppUserDetailsService
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpMethod
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.config.BeanIds
import org.springframework.security.config.annotation
.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation
.web.builders.HttpSecurity
import org.springframework.security.config.annotation
.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation
.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.core.userdetails
.UserDetailsService
import org.springframework.security.crypto.bcrypt
.BCryptPasswordEncoder
import org.springframework.security.web
.DefaultRedirectStrategy
import org.springframework.security.web.RedirectStrategy

@Configuration
@EnableWebSecurity
class WebSecurityConfig(val userDetailsService: AppUserDetailsService) : WebSecurityConfigurerAdapter() {

private val redirectStrategy: RedirectStrategy =
DefaultRedirectStrategy()

@Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http.authorizeRequests()
.antMatchers(HttpMethod.GET,"/register").permitAll()
.antMatchers(HttpMethod.POST,"/users/registrations").permitAll()
.antMatchers(HttpMethod.GET,"/css/**").permitAll()
.antMatchers(HttpMethod.GET,"/webjars/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler { request, response, _ ->
redirectStrategy.sendRedirect(request, response, "/home")
}
.permitAll()
.and()
.logout()
.permitAll()
}

@Throws(Exception::class)
override fun configure(auth: AuthenticationManagerBuilder) {
auth.userDetailsService<UserDetailsService>(userDetailsService)
.passwordEncoder(BCryptPasswordEncoder())
}

@Bean(name = [BeanIds.AUTHENTICATION_MANAGER])
override fun authenticationManagerBean(): AuthenticationManager {
return super.authenticationManagerBean()
}
}

As we have explained earlier in this book, the configure(HttpSecurity) method of WebSecurityConfig has the task of configuring which HTTP URL paths are to be secured and which are not. With the configure(HttpSecurity) method, we have configured Spring Security to permit all HTTP  POST requests to /users/registrations and GET requests whose paths match the paths /register, /css, and /webjars/**. In addition, we have permitted all HTTP requests to a login page that can be accessed from the path /login.

We added a success handler to the login action which utilizes the redirectStrategy property that we defined for our WebSecurityConfig class to redirect a client to the /home path upon successful login of a user. Lastly, we permitted all logout requests to our backend.

configure(AuthenticationManagerBuilder) sets up the UserDetailsService in use and specifies a password encoder to be used. We made use of a BcryptPasswordEncoder in this case. As you may have noticed, we have created no implementation of UserDetailsService in our project. Let us do that now. Add AppUserDetailsService to the com.example.placereviewer.service package:

package com.example.placereviewer.service

import com.example.placereviewer.data.repository.UserRepository
import org.springframework.security.core.GrantedAuthority
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.core.userdetails
.UsernameNotFoundException
import org.springframework.stereotype.Service
import java.util.ArrayList

@Service
class AppUserDetailsService(private val userRepository: UserRepository) : UserDetailsService {

@Throws(UsernameNotFoundException::class)
override fun loadUserByUsername(username: String): UserDetails {
val user = userRepository.findByUsername(username) ?:
throw UsernameNotFoundException("A user with the username
$username doesn't exist")

return User(user.username, user.password,
ArrayList<GrantedAuthority>())
}
}

loadUsername(String) attempts to load the UserDetails of a user matching the username passed to the function. If a user matching the provided username cannot be found, then a UsernameNotFoundException is thrown.

With all this completed, you have successfully set up Spring Security for our backend. Great work!

Now that we have finished work on our entities, repositories, services, service implementations, and Spring Security configuration, we can ideally begin implementing the frontend of our application. However, the implementation of the application's frontend is a task for the next chapter and as such, let us focus on other things. More specifically, let us explore the process of serving web content to a client application with Spring MVC.

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

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