limkinZero / advance-spring-boot-microservice

This repository we will see advance microservice architecture by spring boot, eureka, zuul, hystrix monitoring dashboard, swagger 2 and web services

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Hystrix Dashboard, Swagger2 with secure-spring-boot-microservice

Overview

The architecture is composed by five services:

  • micro-api-getway: API Gateway created by Zuul that is internally uses Ribbon Load Balancer and also can monitor Hystrix stream from every API request by Hystrix

  • micro-eureka-server: Service Registry Server created by Eureka with Load Balancer for inter-service communication

  • micro-auth-service: Simple REST service created with Spring Boot, Spring Cloud Oauth2, Spring Data JPA, MySQL to use as an authorization service

  • micro-item-service: Simple REST service created with Spring Boot, Spring Data JPA, MySQL and swagger to test api to use as a resource service

  • micro-sales-service: Simple REST service created with Spring Boot, Spring Data JPA, MySQL and swagger to test api to use as a resource service

Follow the link to see docker deployment with docker,docker-compose dockerized-spring-boot-microservice

Tools you will need

  • Maven 3.0+ is your build tool
  • Your favorite IDE but we will recommend STS-4-4.4.1 version. We use STS.
  • MySQL server
  • JDK 1.8+

How to run advance microservice?

Application Running Process:

  • First we need to run eureka service
  • Second we need to run auth-service
  • Third we need to run item-servic and sales-service
  • At last we need to run gateway-service, if we did run gateway-service before running auth-service and iteam,sales-service then we have to wait approximately 10 second

Run on sts IDE

click right button on the project >Run As >Spring Boot App

After successfully run then we will refresh eureka dashboard and make sure to run auth, item, sales and gateway on the eureka dashboard.

Eureka Discovery-Service URL: http://localhost:8761

Eureka Service

Eureka Server is an application that holds the information about all client-service applications. Every Micro service will register into the Eureka server and Eureka server knows all the client applications running on each port and IP address. Eureka Server is also known as Discovery Server.

Authorization Service

An Authorization Server issues tokens to client applications on behalf of a Resource Owner for use in authenticating subsequent API calls to the Resource Server. The Resource Server hosts the protected resources, and can accept or respond to protected resource requests using access tokens.

CORS filter Configure

Let’s create a class WebSecurityConfiguration.java to configure CORS Filte.

  • corsFilter Apparently the Oauth2 endpoints and filters get processed before getting to the Spring Security filter chain, so adding CORS filters normally wouldn't work, but adding a CORS filter bean with high order priority ended up working.

    This is my dedicated configuration class for CORS (adapted from the official spring guide, I'll be tweaking it later)

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

	  @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}

Test Authorization Service

Get Access Token

Let’s get the access token for admin by passing his credentials as part of header along with authorization details of appclient by sending client_id client_pass username userpsssword

Now hit the POST method URL via POSTMAN to get the OAUTH2 token.

http://localhost:8180/oauth/token

Now, add the Request Headers as follows −

  • Authorization − Basic Auth with your Client Id and Client secret

  • Content Type − application/x-www-form-urlencoded Screenshot from 2020-12-09 10-22-05

Now, add the Request Parameters as follows −

  • grant_type = password
  • username = your username
  • password = your password Screenshot from 2020-12-09 10-22-12

HTTP POST Response

{
    "access_token": "615ca239-7394-463a-8032-94dddd612dcf",
    "token_type": "bearer",
    "refresh_token": "33a3278e-4d62-4a93-8af6-11c0507b7a78",
    "expires_in": 3478,
    "scope": "READ WRITE"
}

Item Service - resource service

Now we will see micro-item-service as a resource service. The micro-item-service a REST API that lets you CRUD (Create, Read, Update, and Delete) products. It creates a default set of items when the application loads using an ItemApplicationRunner bean.

Setting Up Swagger 2 with a Item Service

To enable the Swagger2 in Spring Boot application, you need to add the following dependencies in our build configurations file.

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.9.2</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-bean-validators</artifactId>
	<version>2.9.2</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.9.2</version>
</dependency>

Now, add the @EnableSwagger2 annotation in your main Spring Boot application. The @EnableSwagger2 annotation is used to enable the Swagger2 for your Spring Boot application. Here have two variable that has clientId and clientSecret value getting from application.properties file

The code for main Spring Boot application is shown below −

@Configuration
@EnableSwagger2
public class SwaggerConfig {
	@Value("${security.oauth2.client.client-id}")
	private String clientId;
	
	@Value("${security.oauth2.client.client-secret}")
	private String clientSecret;
	
	public static final String securitySchemaOAuth2 = "oauth2schema";
	public static final String authorizationScopeGlobal = "global";
	public static final String authorizationScopeGlobalDesc = "accessEverything";
}

Swagger UI With an OAuth-Secured API

Next, create Docket Bean to configure Swagger2 for your Spring Boot application. We need to define the base package to configure REST API(s) for Swagger2.

The Swagger UI provides a number of very useful features that we've covered well so far here. But we can't really use most of these if our API is secured and not accessible.

Let's see how we can allow Swagger to access an OAuth-secured API using the Authorization Code grant type in this example.

We'll configure Swagger to access our secured API using the SecurityScheme and SecurityContext support:

	@Bean
	public Docket itemsApi() {
		return new Docket(DocumentationType.SWAGGER_2).select()
			.apis(RequestHandlerSelectors.basePackage("com.ahasan.sales.controller"))
					.paths(PathSelectors.any()).build()
					.securityContexts(Collections.singletonList(securityContext()))
					.securitySchemes(Arrays.asList(securitySchema())).apiInfo(apiInfo());
	}
	
	private SecurityContext securityContext() {
		return SecurityContext.builder().securityReferences(defaultAuth()).build();
	}

After defining the Docket bean, its select() method returns an instance of ApiSelectorBuilder, which provides a way to control the endpoints exposed by Swagger.

We can configure predicates for selecting RequestHandlers with the help of RequestHandlerSelectors and PathSelectors. Using any() for both will make documentation for our entire API available through Swagger.

Security Configuration

We'll define a SecurityConfiguration bean in our Swagger configuration and set some defaults:

@Bean
public SecurityConfiguration security() {
	return new SecurityConfiguration(clientId, clientSecret, "", "", "Bearer access 		token", ApiKeyVehicle.HEADER, HttpHeaders.AUTHORIZATION, "");
}

SecurityScheme

Next, we'll define our SecurityScheme; this is used to describe how our API is secured (Basic Authentication, OAuth2, …).

private OAuth securitySchema() {
		List<AuthorizationScope> authorizationScopeList = newArrayList();
		authorizationScopeList.add(new AuthorizationScope("READ", "read all"));
		authorizationScopeList.add(new AuthorizationScope("WRITE", "access all"));
//		authorizationScopeList.add(new AuthorizationScope("TRUSTED", "trusted all"));
		List<GrantType> grantTypes = newArrayList();
		GrantType passwordCredentialsGrant = new 		  ResourceOwnerPasswordCredentialsGrant("http://localhost:9191/auth-api/oauth/token");
		grantTypes.add(passwordCredentialsGrant);
		return new OAuth("oauth2", authorizationScopeList, grantTypes);
	}

Note that we used the Authorization Code grant type, for which we need to provide a token endpoint and the authorization URL of our OAuth2 Authorization Server.

And here are the scopes we need to have defined:

private List<SecurityReference> defaultAuth() {
		final AuthorizationScope[] authorizationScopes = new AuthorizationScope[2];
		authorizationScopes[0] = new AuthorizationScope("READ", "read all");
		authorizationScopes[1] = new AuthorizationScope("WRITE", "write all");
//		authorizationScopes[2] = new AuthorizationScope("TRUSTED", "trust all");
		return Collections.singletonList(new SecurityReference("oauth2", authorizationScopes));
	}

Web Security paths configure

Ignoring security for path related to Swagger functionalities:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring()
			.antMatchers("/v2/api-docs",
						"/swagger-resources/**",
						"/swagger-ui.html",
						"/webjars/**",
						"/swagger/**");
	}
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**");
	}
}

Now we can test it in our browser by visiting

Screenshot from 2020-12-07 15-41-54

Oauth2 login UI

Screenshot from 2020-12-07 15-42-08

Test HTTP GET Request on item-service -resource service

curl --request GET 'localhost:8180/item-api/item/find' --header 'Authorization: Bearer 62e2545c-d865-4206-9e23-f64a34309787'
  • Here [http://localhost:8180/item-api/item/find] on the http means protocol, localhost for hostaddress 8180 are gateway service port because every api will be transmit by the
    gateway service, item-api are application context path of item service and /item/find is method URL.

  • Here [Authorization: Bearer 62e2545c-d865-4206-9e23-f64a34309787'] Bearer is toiken type and 62e2545c-d865-4206-9e23-f64a34309787 is auth service provided token

For getting All API Information

On this repository we will see secure-microservice-architecture.postman_collection.json file, this file have to import on postman then we will ses all API information for testing api.

Sales Service -resource service

Now we will see micro-sales-service as a resource service. The micro-sales-service a REST API that lets you CRUD (Create, Read, Update, and Delete) products. It creates a default set of items when the application loads using an SalesApplicationRunner bean.

Setting Up Swagger 2 with a Item Service

To enable the Swagger2 in Spring Boot application, you need to add the following dependencies in our build configurations file.

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.9.2</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-bean-validators</artifactId>
	<version>2.9.2</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.9.2</version>
</dependency>

Now, add the @EnableSwagger2 annotation in your main Spring Boot application. The @EnableSwagger2 annotation is used to enable the Swagger2 for your Spring Boot application. Here have two variable that has clientId and clientSecret value getting from application.properties file

The code for main Spring Boot application is shown below −

@Configuration
@EnableSwagger2
public class SwaggerConfig {
	@Value("${security.oauth2.client.client-id}")
	private String clientId;
	
	@Value("${security.oauth2.client.client-secret}")
	private String clientSecret;
	
	public static final String securitySchemaOAuth2 = "oauth2schema";
	public static final String authorizationScopeGlobal = "global";
	public static final String authorizationScopeGlobalDesc = "accessEverything";
}

Swagger UI With an OAuth-Secured API

Next, create Docket Bean to configure Swagger2 for your Spring Boot application. We need to define the base package to configure REST API(s) for Swagger2.

The Swagger UI provides a number of very useful features that we've covered well so far here. But we can't really use most of these if our API is secured and not accessible.

Let's see how we can allow Swagger to access an OAuth-secured API using the Authorization Code grant type in this example.

We'll configure Swagger to access our secured API using the SecurityScheme and SecurityContext support:

	@Bean
	public Docket salesApi() {
		return new Docket(DocumentationType.SWAGGER_2).select()
			.apis(RequestHandlerSelectors.basePackage("com.ahasan.sales.controller"))
					.paths(PathSelectors.any()).build()
					.securityContexts(Collections.singletonList(securityContext()))
					.securitySchemes(Arrays.asList(securitySchema())).apiInfo(apiInfo());
	}
	
	private SecurityContext securityContext() {
		return SecurityContext.builder().securityReferences(defaultAuth()).build();
	}

After defining the Docket bean, its select() method returns an instance of ApiSelectorBuilder, which provides a way to control the endpoints exposed by Swagger.

We can configure predicates for selecting RequestHandlers with the help of RequestHandlerSelectors and PathSelectors. Using any() for both will make documentation for our entire API available through Swagger.

Security Configuration

We'll define a SecurityConfiguration bean in our Swagger configuration and set some defaults:

@Bean
public SecurityConfiguration security() {
	return new SecurityConfiguration(clientId, clientSecret, "", "", "Bearer access 		token", ApiKeyVehicle.HEADER, HttpHeaders.AUTHORIZATION, "");
}

SecurityScheme

Next, we'll define our SecurityScheme; this is used to describe how our API is secured (Basic Authentication, OAuth2, …).

private OAuth securitySchema() {
		List<AuthorizationScope> authorizationScopeList = newArrayList();
		authorizationScopeList.add(new AuthorizationScope("READ", "read all"));
		authorizationScopeList.add(new AuthorizationScope("WRITE", "access all"));
//		authorizationScopeList.add(new AuthorizationScope("TRUSTED", "trusted all"));
		List<GrantType> grantTypes = newArrayList();
		GrantType passwordCredentialsGrant = new 		  ResourceOwnerPasswordCredentialsGrant("http://localhost:9191/auth-api/oauth/token");
		grantTypes.add(passwordCredentialsGrant);
		return new OAuth("oauth2", authorizationScopeList, grantTypes);
	}

Note that we used the Authorization Code grant type, for which we need to provide a token endpoint and the authorization URL of our OAuth2 Authorization Server.

And here are the scopes we need to have defined:

private List<SecurityReference> defaultAuth() {
		final AuthorizationScope[] authorizationScopes = new AuthorizationScope[2];
		authorizationScopes[0] = new AuthorizationScope("READ", "read all");
		authorizationScopes[1] = new AuthorizationScope("WRITE", "write all");
//		authorizationScopes[2] = new AuthorizationScope("TRUSTED", "trust all");
		return Collections.singletonList(new SecurityReference("oauth2", authorizationScopes));
	}

Web Security paths configure

Ignoring security for path related to Swagger functionalities:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring()
			.antMatchers("/v2/api-docs",
						"/swagger-resources/**",
						"/swagger-ui.html",
						"/webjars/**",
						"/swagger/**");
	}
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**");
	}
}

Now we can test it in our browser by visiting

http://localhost:8180/sales-api/swagger-ui.html

Screenshot from 2020-12-07 15-22-21

Oauth2 login UI

Screenshot from 2020-12-07 15-22-53

Test HTTP GET Request on resource service -resource service

curl --request GET 'localhost:8180/sales-api/sales/find' --header 'Authorization: Bearer 62e2545c-d865-4206-9e23-f64a34309787'
  • Here [http://localhost:8180/sales-api/sales/find] on the http means protocol, localhost for hostaddress 8180 are gateway service port because every api will be transmit by the
    gateway service, sales-api are application context path of item service and /sales/find is method URL.

  • Here [Authorization: Bearer 62e2545c-d865-4206-9e23-f64a34309787'] Bearer is toiken type and 62e2545c-d865-4206-9e23-f64a34309787 is auth service provided token

For getting All API Information

On this repository we will see secure-microservice-architecture.postman_collection.json file, this file have to import on postman then we will ses all API information for testing api.

API Gateway Service

Gateway Server is an application that transmit all API to desire services. every resource services information such us: service-name, context-path will beconfigured into the gateway service and every request will transmit configured services by gateway

Hystrix configure on gateway service

Let's start by configuring hystrix monitoring dashboard on API Gateway Service application to view hystrix stream.

First, we need to add the spring-cloud-starter-netflix-hystrix-dashboard dependency:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

The main application class ZuulApiGetWayRunner to start Spring boot application.

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
@EnableHystrixDashboard
public class ZuulApiGetWayRunner {

	public static void main(String[] args) {
		SpringApplication.run(ZuulApiGetWayRunner.class, args);
		System.out.println("Zuul server is running...");
	}

	@Bean
	public PreFilter preFilter() {
		return new PreFilter();
	}

	@Bean
	public PostFilter postFilter() {
		return new PostFilter();
	}

	@Bean
	public ErrorFilter errorFilter() {
		return new ErrorFilter();
	}

	@Bean
	public RouteFilter routeFilter() {
		return new RouteFilter();
	}
}

@EnableHystrixDashBoard – To give dashboard view of Hystrix stream.

@EnableCircuitBreaker – To enable Circuit breaker implementation.

Zuul routes configuration Open application.properties and add below entries-

#Set the Hystrix isolation policy to the thread pool
zuul.ribbon-isolation-strategy=thread

#each route uses a separate thread pool
zuul.thread-pool.use-separate-thread-pools=true

Hystrix dashboard view

  • To monitor via Hystrix dashboard, open Hystrix dashboard at http://localhost:8180/hystrix

Screenshot from 2020-12-07 12-44-38

  • Now view hystrix stream in dashboard – http://localhost:8180/actuator/hystrix.stream

Screenshot from 2020-12-07 12-04-26

To make sure all service is runinng

After sucessfully run we can refresh Eureka Discovery-Service URL: http://localhost:8761 will see zuul-server on eureka dashboard. the gateway instance will be run on http://localhost:8180 port

Screenshot from 2020-11-15 11-21-33

After we seen start auth, sales, item, zuul instance then we can try advance-microservice-architecture.postman_collection.json imported API from postman with token

Docker-Deployment with advance-microservice

Below we will see how to configure docker and docker-compose in microservice

To follow link dockerized-spring-boot-microservice

About

This repository we will see advance microservice architecture by spring boot, eureka, zuul, hystrix monitoring dashboard, swagger 2 and web services


Languages

Language:Java 100.0%