-
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 -
eureka-server: Service Registry Server created by Eureka with Load Balancer for inter-service communication -
auth-service: Simple REST service created withSpring Boot, Spring Cloud Oauth2, Spring Data JPA, MySQLto use as an authorization service
Follow the link to see docker deployment with docker,docker-compose dockerized-spring-boot-microservice
- 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+
Application Running Process:
- First we need to run
eureka service - Second we need to run
auth-service - Third we need to run
item-servicandsales-service - At last we need to run
gateway-service, if we did rungateway-servicebefore runningauth-service and iteam,sales-servicethen 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 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.
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.
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;
}
}
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 yourClient IdandClient secret
Now, add the Request Parameters as follows −
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"
}
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.
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";
}
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.
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, "");
}
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));
}
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("/**");
}
}
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 thehttpmeans protocol,localhostfor hostaddress8180are gateway service port because every api will be transmit by the
gateway service,item-apiare application context path of item service and/item/findis method URL. -
Here
[Authorization: Bearer 62e2545c-d865-4206-9e23-f64a34309787']Beareris toiken type and62e2545c-d865-4206-9e23-f64a34309787is auth service provided token
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.
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.
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";
}
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.
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, "");
}
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));
}
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("/**");
}
}
http://localhost:8180/sales-api/swagger-ui.html
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 thehttpmeans protocol,localhostfor hostaddress8180are gateway service port because every api will be transmit by the
gateway service,sales-apiare application context path of item service and/sales/findis method URL. -
Here
[Authorization: Bearer 62e2545c-d865-4206-9e23-f64a34309787']Beareris toiken type and62e2545c-d865-4206-9e23-f64a34309787is auth service provided token
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.
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
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-hystrix-dashboard dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.7.RELEASE</version>
</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
- To monitor via Hystrix dashboard, open Hystrix dashboard at
http://localhost:8180/hystrix
- Now view hystrix stream in dashboard –
http://localhost:8180/hystrix.stream
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
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








