Spring security with spring boot example

Spring Security is a framework what spring calls it. It provides authentication, authorization, and protection against attacks. It has become kind of a standard for securing spring based applications.
In this tutorial we will learn about spring security with spring boot and its example.

Spring Security requires a Java 8 or higher Run-time Environment.

Spring security Features

  1. Authentication
  2. Authorization
  3. Protection against common exploits

1. Authentication

There are many ways to authenticate users, like the most common way is by requiring user to enter username and password. There are many Password Storage Techniques like.

Using Spring Security PasswordEncoder.
Using BCryptPasswordEncoder.
Using DelegatingPasswordEncoder.
Using NoOpPasswordEncoder.

2. Protection against common exploits

Spring Security provides protection against common exploits. Whenever possible, the protection is enabled by default.

CSRF (Cross Site Request Forgery) Attacks
Default Security Http Headers.

Example : Default Security HTTP Response Headers

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=bloc

3. Http

As a framework, Spring Security does not handle HTTP connections and thus does not provide support for HTTPS directly. However, it does provide a number of features that help with HTTPS usage, like.

Redirect to HTTPS
Strict Transport Security
Proxy Server Configuration

Spring Security with Spring Boot Example

1. Project Structure

springboot-spring-security-project-structure

2. REST Controller – EmployeeController

First creating a REST controller class like this, with few HTTP methods like GET, POST, DELETE.

package com.programmertoday.springsecurity.controller;

import com.programmertoday.springsecurity.model.Employee;
import com.programmertoday.springsecurity.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("api")
public class EmployeeController {

@Autowired
EmployeeService empService;

// Get all Employees
@GetMapping("/employees")
List<Employee> findAll() {
return empService.findAll();
}

// Save Employees
@PostMapping("/employees")
@ResponseStatus(HttpStatus.CREATED)
String newEmployee(@RequestBody Employee newEmployee) {

empService.save(newEmployee);
return "Success fully created Employees";
}

// Delete Employees with id
@DeleteMapping("/employees/{id}")
String deleteBook(@PathVariable Integer id) {

empService.deleteEmpById(id);
return "deleted employee with id " +id + " successfully";
}
}

3. Model Class – Employee

package com.programmertoday.springsecurity.model;

public class Employee {

private int empId;
private String empName;
private String empDept;
private String empLocation;

public Employee(int empId, String empName,
String empDept, String empLocation) {
this.empId = empId;
this.empName = empName;
this.empDept = empDept;
this.empLocation = empLocation;
}

public int getEmpId() {
return empId;
}

public void setEmpId(int empId) {
this.empId = empId;
}

public String getEmpName() {
return empName;
}

public void setEmpName(String empName) {
this.empName = empName;
}

public String getEmpDept() {
return empDept;
}

public void setEmpDept(String empDept) {
this.empDept = empDept;
}

public String getEmpLocation() {
return empLocation;
}

public void setEmpLocation(String empLocation) {
this.empLocation = empLocation;
}
}

4. Service class – EmployeeService

package com.programmertoday.springsecurity.service;

import com.programmertoday.springsecurity.model.Employee;
import org.springframework.stereotype.Service;

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

@Service
public class EmployeeService {

public List<Employee> findAll() {
List<Employee> empList = new ArrayList<>();
empList.add(new Employee(101,"Maverick","RE","SF"));
empList.add(new Employee(102,"John","CS","NJ"));
empList.add(new Employee(103,"Drake","HE","NYC"));
return empList;
}

public void save(Employee newEmployee) {

System.out.println("saving new employee");
// .. add your own code, it's just for basic understanding
}

public void deleteEmpById(Integer id) {

// .. add your own code, it's just for basic understanding
System.out.println("Employee with "+id+" is deleted");
}

}

5. Config class – SpringSecurityConfig

package com.programmertoday.springsecurity.configs;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.WebSecurityConfigurerAdapter;

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

// Creating just 2 users for demonstration
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER")
.and()
.withUser("admin").password("{noop}password").roles("USER", "ADMIN");

}

// Securing the endpoints with HTTP Basic authentication
@Override
protected void configure(HttpSecurity http) throws Exception {

http
//HTTP Basic authentication
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/employees/**").hasRole("USER")
.antMatchers(HttpMethod.POST, "/api/employees").hasRole("ADMIN")
.antMatchers(HttpMethod.DELETE, "/api/employees/**").hasRole("ADMIN")
.and()
.csrf().disable()
.formLogin();//.disable();

}

}

6. SpringBootApplication – SpringSecurityApplication Class

Now run the application.

package com.programmertoday.springsecurity;

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

@SpringBootApplication
public class SpringSecurityApplication {

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

}

OUTPUT

Example 1 : Unauthorized Login Unsuccessful because of Spring Security

// With a different user(user123) who is not an authorized user
C:\>curl localhost:8080/api/employees -u user123:password
{“timestamp”:”2020-04-05T14:39:25.805+0000″,”status”:401,”error”:”Unauthorized”,”message”:”Unauthorized”,”path”:”/api/employees”}

// Calling Delete API with a user who is not authorized to access Delete API
C:\>curl -X DELETE localhost:8080/api/employees/1 -u user:password
{“timestamp”:”2020-04-05T14:37:23.688+0000″,”status”:403,”error”:”Forbidden”,”message”:”Forbidden”,”path”:”/api/employees/1″}

Example 2 : Successful Login

GET API : with user=user and password=password

C:\>curl localhost:8080/api/employees -u user:password
[{“empId”:101,”empName”:”Maverick”,”empDept”:”IT”,”empLocation”:”SF”},{“empId”:102,”empName”:”John”,”empDept”:”CS”,”empLocation”:”NJ”},{“empId”:103,”empName”:”Drake”,”empDept”:”HE”,”empLocation”:”NYC”}]

DELETE API Call : with user=admin and password=password

C:\> curl -X DELETE localhost:8080/api/employees/1 -u admin:password
deleted employee with id 1 successfully

Try testing in Browser as well

Open the browser : localhost:8080/api/employees – it will redirect to /login first

Provide the right credentials as configured in the SpringSecurityConfig class

spring-security-api-login
spring-security-api-example

Summary

In this tutorial we learnt how to use spring security with REST APIs and spring boot. We created a spring boot REST based simple project and secured it using spring security. At the end we also saw the output of the code using curl command lines as well as in the browser.

Please comment below for suggestions and questions, I hope you liked it !


Spring – Transaction Management in Spring

A database transaction is a sequence of actions that are treated as a single unit of work. These actions should either complete entirely or take no effect at all. Transaction management is an important part of RDBMS-oriented enterprise application to ensure data integrity and consistency.
The concept of transactions can be described with the following four key properties described as ACID −

Atomicity − A transaction should be treated as a single unit of operation, which means either the entire sequence of operations is successful or unsuccessful.

Consistency − This represents the consistency of the referential integrity of the database, unique primary keys in tables, etc.

Isolation − There may be many transaction processing with the same data set at the same time. Each transaction should be isolated from others to prevent data corruption.

Durability − Once a transaction has completed, the results of this transaction have to be made permanent and cannot be erased from the database due to system failure.

Summary

In this tutorial we learnt about Spring Transaction Management and the principle of ACID properties it follows.
Hope you liked it !


Spring AOP – Aspect Oriented Programming

AOP is like triggers in programming languages such as Perl, .NET, Java, and others.
Spring AOP module provides interceptors to intercept an application. For example, when a method is executed, you can add extra functionality which executes always before or after the method execution using annotations and xml configurations.
AOP involves breaking down program logic into distinct parts called concerns. Aspects enable the modularization of concerns that cut across multiple types and objects (often termed crosscutting concerns).
Common examples are – logging, auditing, transactions, security, caching, etc.

Given a scenario :

You have to maintain log and send notifications when methods starting with *serviceImpl are called.
One way : is to write the log statements in every serviceImpl methods
Problem : after you write the logs, if requirement comes to change the logging statment, then you need to change it in every possible method where you wrote the log statement, it leads to severe maintenance problem.
Better way : Define a concerns and use it. Even if you want to change the logs then you need to change it at only one place and not in every file.

AOP terminologies

1. Aspect : An Aspect is the concern (cross cutting concern) which you want to implement in the application such as logging, performance monitoring, transactional handing etc.

2. Advice : An Advice is the actual implementation of the aspect. Aspect is a concept and Advice is the concrete implementation of the concept.

3. Join Point : JoinPoint is a point in the execution of the program where an aspect can be applied. It could be before/after executing the method, before throwing an exception, before/after modifying an instance variable etc. Keep in mind that it is not necessary and also not required to apply an aspect at all the available join points. Spring AOP only supports method execution join points.

4. Aspect : An Aspect is the concern (cross cutting concern) which you want to implement in the application such as logging, performance monitoring, transactional handing etc.

5. Point cut : PointCuts tell on which join points the aspect will be applied. An advice is associated with a point cut expression and is applied to a join point which matches the point cut expression.

6. Target : An Aspect is the concern (cross cutting concern) which you want to implement in the application such as logging, performance monitoring, transactional handing etc.

7. Weaving : Weaving is the process of linking aspects with other application types or objects to create an advised object. This can be done at compile time, load time, or at runtime.

Types of Advice Spring aspects work with these advice

  • Before Advice: it executes before a join point.
  • After Returning Advice: it executes after a joint point completes normally.
  • After Throwing Advice: it executes if method exits by throwing an exception.
  • After (finally) Advice: it executes after a join point regardless of join point exit whether normally or exceptional return.
  • Around Advice: It executes before and after a join point.

Summary

In this tutorial we learnt about Spring Aspect Oriented Programming, AOP terminologies, a scenario where it can be used and types of Advice.
Hope you liked it !


Spring DI – Dependency Injection in spring

It is the heart of spring framework, it facilitates the idea of keeping classes independent of each other and injecting them wherever required. DI helps decouple your application objects from each other.

Spring framework provides two ways to inject dependency

1. By Constructor
2. By Setter method

1. By Constructor Injection

It is achieved when the container invokes the target constructor with the number of arguments. Below is an example where a class is injected to another via constructor by passing the reference as constructor arguments.


/********Mobile class*********/
public class Mobile {
    private Recharge recharge;
    
    public Mobile(Recharge recharge) {}
      System.out.println("Inside Mobile constructor." );
      this.recharge = recharge;
    }
    public void getRecharge() {
      recharge.doRecharge();
    }
    }
}
/********Recharge class*********/			
public class Recharge {}
    public Recharge(){
      System.out.println("Inside Recharge constructor." );
    }
    }
    public void doRecharge() {
      System.out.println("Inside doRecharge." );
    }
    }
}
/********Main class*********/
public class MainApp {
    public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

    Mobile mb = (Mobile) context.getBean("mobile");
    mb.getRecharge();
    }
}

/********Beans.xml*********/
<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation = "http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- Definition for Mobile bean -->
    <bean id = "mobile" class = "com.programmertoday.Mobile">
      <constructor-arg ref = "recharge"/>
    </bean>

    <!-- Definition for Recharge bean -->
    <bean id = "recharge" class = "com.programmertoday.Recharge"></bean>

</beans>

OUTPUT:
------
Inside Recharge constructor.
Inside Mobile constructor.
Inside doRecharge.

2. By Setter Injection

It is achieved when the container invokes the setter methods on your beans after calling a no-arg constructor or no-arg static factory method to instantiate your bean.

public class TextEditor {
    private SpellChecker spellChecker;

    // a setter method to inject the dependency.
    public void setSpellChecker(SpellChecker spellChecker) {
      System.out.println("Inside setSpellChecker." );
      this.spellChecker = spellChecker;
    }
    // a getter method to return spellChecker
    public SpellChecker getSpellChecker() {
      return spellChecker;
    }
    public void spellCheck() {
      spellChecker.checkSpelling();
    }
}

Difference between constructor and setter injection

FactorSI(Setter Injection)CI(Constructor Injection)
Partial dependencyCan be injected using setter injection, e.g if there is a Bean with 4 properties having 4 args constructor and setter methods, and if you want to pass value for only one property from other class its possible by setter method only.Not possible with constructor injection.
OverridingIf both the types of DI are present in a file then the SI overrides the CI.Less priority over SI
Easy ChangesNo need to create an instance of a class to change a value using setter injection.But using constructor injection one has to create a new bean instance.

Summary

In this tutorial we learnt about Spring Dependency Injection, two types of dependency injection (constructor and setter) and its difference.
Hope you liked it !