Spring

IoC, DI, DIP

IoC - In the context of service containers, IoC is achieved by allowing the framework to do the binding and instantiation of dependencies. Instead of the application having to create and use services, it is the framework that determines the moment when the instantiation is needed.

Dependency injection - Dependency Injection was the name coined by Martin Fowler in 2004 to have a better, and more specific name for this style, as opposed to the overly generic term Inversion of Control used by many frameworks.

Dependency Injection is a software design technique in which the creation and binding of dependencies are done outside of the dependent class. Afterwards, said dependencies are provided already instantiated and ready to be used, hence the term “injection”; in contrast to the dependent class having to instantiate its dependencies internally, and having to know how to configure them, thus causing coupling.

Dependency Inversion Principle (DIP)

  • High-level modules should not depend on low-level modules. Both should depend on abstractions.

  • Abstractions should not depend on details. Details should depend on abstractions.

the dependency direction is inverted, interfaces are determined at a higher level and classes in their same level depend on them, therefore they depend on abstractions. Additionally, lower-level class implementations depend on the interfaces defined at a higher level, therefore details now depend on abstractions.

If both client and service depend on an abstraction, then you essentially have an agreement that, if respected, will allow for the following:

  • The client will be agnostic of who the dependency is, and instead rely on what it does

  • The dependency will be guaranteed to behave in a way that is determined by the high-level policy

  • The client can be reused in other contexts safely, trusting that its dependencies will respect the contract

  • The dependency can always be replaced by another implementation that implements the same contract

Good examples of full apps

Microservice app with deployment and monitoring

Dependencies

  • spring-boot-dev-tools

    • helps with hot reload of code changes (works faster then server restart)

Properties

An order of property file loading

  • bootstrap.properties

  • application.properties

Spring expression language

Basic Auth

  • GET/... Request | Basic64 username:password Header for every request

  • Header Authorization: Basic [hash]

  • Can not logout

  • HTTPS recommended

  • Simple and fast

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

@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/", "index", "/css/*", "/js/*")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
    }
}

CSRF (Cross site request forgery)

  • CSRF token have to be used for frond end backend communication

  • for backend-backend not mandatory

Code pointers:

  • CookieCsrfTokenRepository

  • CsrfFilter

OAuth2 authorization server

@EnableAuthorizationServer

  • enables Authorization Server

    • o.s.s.o.provider.endpoint.AuthorizationEndpoint

    • o.s.s.o.provider.endpoint.TokenEndpoint

    • see also o.s.s.o.c.a.w.configuration.AuthorizationServerEndpointsConfiguration

  • How to configure server? extend o.s.s.o.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter

  • The user is responsible for securing "Authorization Endpoint" (/oauth/authorize) using normal Spring security features (i.e @EnableWebSecurity)

  • But Token Endpoint (/oauth/token) is auto secured using HTTP Basic authentication on the client credentials

  • Clients must be registered by providing a o.s.s.o.provider.ClientDetailsService through one or more AuthorizationServerConfigurers

    • loadClientByClientId

Authorization endpoint

  • Implementation of the Authorization Endpoint from the OAuth2 specification

  • Accepts authorization requests and handles user approval if the grant type is authorization code

  • Should be secured. Only accessible to fully authenticated users

  • POST /oauth/authorize param: user_oauth_approval

TokenEndpoint

  • Clients post requests with a grant_type parameter (e.g. "authorization_code") and others as determined by grant type

  • Supported grant types are handled by o.s.s.o.provider.TokenGranter

  • Clients must be authenticated (o.s.s.core.Authentication ) to access this endpoint and the client id is extracted from the authentication token

    • best way: HTTP basic auth

  • GET /oauth/token

  • POST /oauth/token

OAuth2 client

@EnableOAuth2Client

Authorization Code Grant

  • Enable configuration for an OAuth2 client in a web application that uses Spring Security and wants to use the Authorization Code Grant from one or more OAuth2 Authorization servers.

  • you need a global servlet filter org.springframework.web.filter.DelegatingFilterProxy that delegates to a bean named oauth2ClientContextFilter .

  • Once that filter is in place your client app can use another bean provided by annotation o.s.s.o.client.token.AccessTokenRequest to create a o.s.s.o.client.OAuth2RestTemplate .

@Bean
   public OAuth2RestOperations restTemplate(OAuth2ClientContext oauth2ClientContext) {
  		return new OAuth2RestTemplate(remote(), oauth2ClientContext);
  }

Client credentials grant

  • do not need AccessTokenRequest or scoped RestOperations

  • they still need to use a filter to trigger OAuth2RestOperations to obtain a token when necessary

Password grant

  • apps needs to set authentication properties in the OAuth2ProtectedResourceDetails before using the RestOperation

  • This means the resource details themselves also have to be per session

Gateway

Spring Boot + WebFlux + Project Reactor

Web Filters (Gateway filters)

The Handler Mapping manages the client's request. It checks whether it matches some configured route. Then, it sends the request to the Web Handler to execute the specific filter chain for this route. The dotted line splits the logic between pre- and post-filter logic. The income filters run before the proxy request. The output filters enter into action when they receive the proxy response. Filters provide mechanisms to modify the process in between.

Good article

Security

JWT

Good video Security + JWT

Spring Session

About HTTP session. Makes it easy to share sessions between services.

Storage for session:

  • JDBC

  • Gemfire (in-memory data grid)

  • MongoDB

  • Redis

Microservice system participants

Spring Cloud Config is Spring's client/server approach for storing and serving distributed configurations across multiple applications and environments.

This configuration store is ideally versioned under Git version control and can be modified at application runtime. While it fits very well in Spring applications using all the supported configuration file formats together with constructs like Environment, PropertySource or @Value, it can be used in any environment running any programming language.

Discovery service (Eureka)

Intro link

Actually available discovery services in Spring cloud world:

  • Eureka

  • Zookeeper

  • Cloud Foundry

  • Consul

  1. Service A and service B registers in Eureka server, providing their application names and network locations.

  2. Service A intends to access Service B. Therefore, it possesses the application name (not the network location) of service B.

  3. Service A presents the application name of Service B to Eureka server and obtains the corresponding network location.

  4. Service A uses the obtained network location of service B to make a request (via http or some other protocol).

Eureka Client Server Communication

  • Register: Eureka client registers the information about the running instance to the Eureka server.

  • Renew: Eureka client needs to renew the lease by sending heartbeats every 30 seconds. The renewal informs the Eureka server that the instance is still alive. Special Note: Eureka server doesn’t poll service instances (client) to find out their availability. Instead, clients send a heartbeat to Eureka server to inform their availability.

  • Fetch Registry: Eureka clients fetches the registry information from the server and caches it locally. After that, the clients use that information to find other services.

  • Cancel: Eureka client sends a cancel request to Eureka server on shutdown. This removes the instance from the server’s instance registry thereby effectively taking the instance out of traffic.

  • Server Cluster: Eureka can be deployed as a cluster of servers. In case, one of these Eureka servers crash, clients can still connect to the remaining Eureka servers and discover other services.

  • Client Side Caching: Clients retrieve and cache registry information from Eureka server. In case all Eureka servers crash, clients still posses the last healthy snapshot of the registry. This is the default behaviour of Eureka clients and you don’t have to make any additional configurations to enable client side caching.

Server cluster

Eureka clients are aware of all the available server peers and in case one server crashes, they connect to the remaining servers and fetch registry information.

An example can be found here based on the article.

Last updated