In this tutorials, I am going to show how to secure spring boot rest endpoints using Spring Boot in memory basic authentication.

Spring Boot In Memory Basic Authentication:

As part of this tutorials, I am going to create a simple spring boot rest service which provides 3 basic endpoints such as reading, creating and deleting Items and these 3 endpoints have to be secured.

Spring Boot In Memory Basic Authentication Example:

Here, I am going to create a 2 different roles ADMIN and USER.

The users which are having ADMIN role can be accessible to Create and Delete Items. The USER role can be accessible to reading Items.

Technologies Used:

  • Spring Boot 2.0.5
  • Spring Boot Security
  • Java 8
  • Maven

Application Structure:

Spring Boot In Memory Basic Authentication Example

Project Dependencies:

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.onlinetutorialspoint</groupId>
  <artifactId>SpringBoot-InMemory-Security-Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>SpringBoot-InMemory-Security-Example</name>
  <description>Spring Boot In Memory Basic Authentication Security</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

Security Configuration.

Creating 2 users: chandra and admin using Spring Boot’s in-memory AuthenticationManagerBuilder and assigned roles with USER and ADMIN respectively.

SecurityConfig.java
package com.onlinetutorialspoint.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder managerBuilder) throws Exception{
        managerBuilder.inMemoryAuthentication()
                .withUser("chandra").password("{noop}1234").roles("USER").and()
                .withUser("admin").password("{noop}admin123").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.httpBasic().and().authorizeRequests()
                .antMatchers("/addItem","/delete").hasRole("ADMIN")
                .antMatchers("/getAllItems").hasRole("USER")
                .and().csrf().disable().headers().frameOptions().disable();
    }
}

Creating Item Model

Item.java
package com.onlinetutorialspoint.model;

import java.io.Serializable;

public class Item implements Serializable {
    private Integer id;
    private String name;
    private String category;

    public Item() {
    }

    public Item(Integer id, String name, String category) {
        this.id = id;
        this.name = name;
        this.category = category;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }
}

Creating Item Service

ItemService.java
package com.onlinetutorialspoint.services;

import com.onlinetutorialspoint.model.Item;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Repository
public class ItemService {
    public static List<Item> items;
    static{
        items = new ArrayList<>(Arrays.asList(new Item(1,"Spring Boot in Action","Books"),
                new Item(2,"Java 8 in Action","Books"),
                new Item(3,"Data Structures","Books")));
    }

    public List<Item> getAllItems(){
        return items;
    }

    public void addItem(Item item){
        items.add(item);
    }
    public void deleteItem(int id){
        items.removeIf(i -> i.getId().equals(id));
    }

}

Creating Item Controller

ItemController.java
package com.onlinetutorialspoint.controller;

import com.onlinetutorialspoint.model.Item;
import com.onlinetutorialspoint.services.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;

@RestController
public class ItemController {
    @Autowired
    ItemService itemService;

    @RequestMapping("/getAllItems")
    @ResponseBody
    public ResponseEntity<List<Item>> getAllItems(){
        List<Item> items =  itemService.getAllItems();
        return new ResponseEntity<List<Item>>(items, HttpStatus.OK);
    }

    @PostMapping(value = "/addItem",consumes = {"application/json"},produces = {"application/json"})
    @ResponseBody
    public ResponseEntity<Item> addItem(@RequestBody Item item,UriComponentsBuilder builder){
        itemService.addItem(item);
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(builder.path("/addItem/{id}").buildAndExpand(item.getId()).toUri());
        return new ResponseEntity<Item>(headers, HttpStatus.CREATED);
    }

    @DeleteMapping("/delete/{id}")
    @ResponseBody
    public ResponseEntity<Void> deleteItem(@PathVariable int id){
        itemService.deleteItem(id);
        return new ResponseEntity<Void>(HttpStatus.ACCEPTED);
    }
}

Main class:

Application
package com.onlinetutorialspoint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

Run the application:

Console
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.5.RELEASE)

2018-10-21 13:00:44.551  INFO 6856 --- [           main] com.onlinetutorialspoint.Application     : Starting Application on DESKTOP-RN4SMHT with PID 6856 (E:\work\SpringBoot-InMemory-Security-Example\target\classes started by Lenovo in E:\work\SpringBoot-InMemory-Security-Example)
2018-10-21 13:00:44.559  INFO 6856 --- [           main] com.onlinetutorialspoint.Application     : No active profile set, falling back to default profiles: default
....
....

Access the application:

Reading allItems with valid user credentials.

Spring Boot In Memory Basic Authentication ReadAll Success

Reading allItems with invalid user credentials.

Spring Boot In Memory Basic Authentication ReadAll Unauthorized

Deleting Item with admin user.

Spring Boot In Memory Basic Authentication Delete Success

Deleting an Item with an unknown user.

Spring Boot In Memory Basic Authentication Delete Unauthorized

References:

Spring Boot Security Docs

Happy Learning 🙂

Download Example