Thursday, 21 September 2017

Simple example of Secured Spring Boot Restful webservice application

A web service is a method of communication between multiple devices over the World Wide Web. Using Web Services, we can publish application's functions to everyone. In the web services world, REpresentational State Transfer (REST) is a key design idiom that embraces a stateless client-server architecture in which the web services are viewed as resources and can be identified by their URLs. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods.

  • To create a resource on the server, use POST .
  • To retrieve a resource, use GET .
  • To change the state of a resource or to update it, use PUT .
  • To remove or delete a resource, use DELETE .
More details about RESTFul web services please go to references section of this blog. This Blog instruction will help us to create a sample RESTful webservice application using spring boot services.

Earlier we have discussed implementation process of Restfulwebservice app using CXF JAX-RS services. This time I decided to implement microservices. Regarding microservices architecture I have followed my development/design experiences and microservice Io. It will be great if readers share their own experiences and point of view on the topic microservices architecture. To keep it simple in this blog instruction will we will discuss implementation steps. Regarding spring boot application I followed amazining documentation provided by spring io spring Io.

I have also deployed this example app on cloud systems like Heroku and RedHat Openshift. So readers can explore them real-time. Demostration application services are available at

For API documentation purpose this app has been integrated with swagger2


  • Implemenation instructions
  • Create a spring starter project name "com.kaustuv.spring.example" using spring sts plugin. Add the following dependency in maven dependencies section.
  • Application classpath
    1. spring-boot-starter 1.5.6
    2. spring-boot-starter-web 1.5.6
    3. spring-boot-starter-web 1.5.6
    4. spring-boot-starter-cache 1.5.6
    5. spring-boot-autoconfigure 1.5.6
    6. spring-boot-starter-aop 1.5.6
    7. spring-boot-starter-security 1.5.6
    8. spring-boot-starter-logging 1.5.6
    9. spring-boot-starter-actuator 1.5.6
    10. ehcache
    11. log4j
    12. springfox-swagger2

    For design and implementation I tried to follow GOF Domain driven design architechture. Now I will explain layer of the application.

    ⇢ Domain Layer

  • Create package com.example.demo.domain
  • Create simple domain class Employee and following snippet.

  • Create interface which will contain domain services and add following snippet.
  • We will define all following methods of CRUD functions.

    Application Layer

  • create package com.example.demo.application
  • create Application service class EmployeeServiceImpl which will implement the domain service interface EmployeeService.
  • Please note there are two cacheable Read methods provided by the application service class.
    1. getEmployee method
     
     @Cacheable(value = "employeeCache", key = "#id", sync = true)
     @Override
     @LogMethodExecution
     public Employee getEmployee(Integer id) {
      return employees.get(id);
     }
    
    The employee id is used as a key of cache. by using sync=true arguments we trigger spring caching technology to sync the object state only if there is any change.
    2. getEmployees method
     
     @Cacheable(value = "employeeCache", sync = true)
     @LogMethodExecution
     public Collection getEmployees() {
      return employees.values();
     }
    
  • create package com.example.demo.application.aop
  • create custom annotation interface LogMethodExecution
  • create Application AOP aspect class LogAspect @Aspect. logExecutionTime method provides log method exustion details for application service Methods annoted with @LogMethodExecution.

  • ⇢ Interface Layer

  • Create Rest Controller EmployeeRestController. This controller class is responsible for publishing restful services for Employee at url mapping "/employee/services".
  • Method Name HTTP Method url mapping description
    getEmployees GET "/employee/services/listOfEmployee" fetch list employee detail avilable in system
    getEmployee GET "/employee/services/employeeDetail" fetch employee detail by id
    addEmployees POST "/employee/services/addEmployee" Add Employee
    updateEmployee PUT "/employee/services/updateEmployee" Employee details update.
    deleteEmployee DELETE "/employee/services/deleteEmployee" Employee deletion


    We have implemented spring role based security with method level annotation org.springframework.security.access.prepost.@PreAuthorize
    Method Name Security Annotation
    getEmployees ROLE_ADMIN @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    getEmployee ROLE_ADMIN @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    addEmployees ROLE_ADMIN @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    updateEmployee ROLE_ADMIN @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    deleteEmployee ROLE_ADMIN @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    Enabled restful webservice documentaiton using swagger 2 annotation.

    import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.Authorization;

  • Create spring configuration class LoggingFilterConfig. this class will customize the HTTP request/response message displayed in application log.
  • Create spring configuration class Swagger2Config. this class enables the swagger2 api documentation. springfox.documentation.swagger2.annotations.@EnableSwagger2
  • Create spring configuration class ScheduleJob. this class demonstrates how to enable spring scheduler job in spring boot app by using annotation @EnableScheduling.

  • Create com.example.demo.security package. Will package contains all the security related implementation classes
  • Create Application User class which holds the application user details.
    Create custom authentication provider class which provides the authentication logic. For this app, we have enabled username-password token security. To keep it simple we have used hashmap as a container to hold app user details. It's possible to use LDAP or database to keep app user details. We have implemented the authenticate() of AuthenticationProvider interface.
    Create RestAppSecurity class and extend WebSecurityConfigurerAdapter. This class enables (@EnableWebSecurity) the and hold security feature for our example application. Using this class we can achieve two type of restful app security.
        Secnario 1 Roles based authentication using url. (using inMemoryAuthentication)
       
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      
      /*
       * Scenario 1. using inMemoryAuthentication
       */
       auth.inMemoryAuthentication().withUser("admin").password("admin@123").roles("ADMIN").
       // Admin user
       and().withUser("user1").password("user@123").roles("USER"). // local user
       and().withUser("kaustuv").password("pass@123").roles("USER", "ADMIN"); // Myself having both
      }
      
       @Override
      protected void configure(HttpSecurity http) throws Exception {
      // Scenario 1. url path configuration.
       http.httpBasic().and().authorizeRequests().antMatchers("/employee/**").hasRole("ADMIN").antMatchers("/**")
       .hasRole("USER").and().csrf().disable().headers().frameOptions().disable();
      
      
      // maximum session allowed session
      http.sessionManagement().maximumSessions(5).sessionRegistry(sessionRegistry());
      }
       
        Scenario 2 Roles based authentication using method level Annotation (@EnableGlobalMethodSecurity) using custom authentication provider.
       
      @Autowired
      RestAppAuthenticationProvider restAppAuthenticationProvider;
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      
      /*
       * Scenario 2. Example of AuthenticationProvider
       */
      auth.authenticationProvider(restAppAuthenticationProvider);
      }
      
      @Override
      protected void configure(HttpSecurity http) throws Exception {
      // Scenario 2. this configuration is for method level configuration.
      http.httpBasic().and().authorizeRequests().anyRequest().authenticated().and().csrf().disable().headers()
        .frameOptions().disable();
      
      // maximum session allowed session
      http.sessionManagement().maximumSessions(5).sessionRegistry(sessionRegistry());
      }
       

    ⇢ Application Configuration Layer

  • Create a package com.example.demo.app.configuration.
  • Create a spring configuration class CacheConfigurerAdapter. This class enables annotation based spring cache feature . @EnableCaching. Create ehcache configuration xml (ehcache.xml) create cache name employeeCache. Configuration path src/main/resources/ehcache.xml


  • In Above file we have created employeeCache by following EhCache documentation.
  • create spring confiuration class CustomWebMvcConfigurerAdapter.java. This class is responsible for enabling spring MVC feature. It loads required swagger HTML and js files as a spring web application resources

  • ⇢ Spring Boot App Runner

  • create spring boot application main/runner class DemoApplication. @SpringBootApplication annotation enables this class as a spring boot application runner class.

  • application properties
  • Above files hold the application configuration properties. For example, we have configuration log category, mentioned eh-cache configuration file. We can do many things check the following link for more details Spring application properties

        Post Development deployment

    1. Build the application using following maven command
    2.  
        $ mvn clean install
       
    3. Once the build is done. use following command to start the spring boot application.
    4.  
        $ java -jar target/com.kaustuv.spring.example.boot.rest-0.0.1-SNAPSHOT.jar 
       
    5. After sucessfull deployment services will be available at http://localhost:8080
    6. Use following command to start the spring boot application in debug mode.
    7.  
        $ java -Ddebug -jar target/com.kaustuv.spring.example.boot.rest-0.0.1-SNAPSHOT.jar 
       

        Post Deployment testing


      Load following soapui project file in soap ui app. and Execute testcases. Reader can use swagger html page as well to test the apis.
    Click here to download source code of above example

    Source Code


    • References:
    Spring Boot
    EhCache
    swagger2
    http://www.baeldung.com
    Soapui
    http://www.baeldung.com

    European Union laws require you to give European Union visitors information about cookies used on your blog. In many cases, these laws also require you to obtain consent.

    As a courtesy, we have added a notice on your blog to explain Google's use of certain Blogger and Google cookies, including use of Google Analytics and AdSense cookies.

    No comments:

    Post a Comment