Categories: Uncategorised

Simple application developed using microservices deployed on AWS

Microservices are a modern approach to software whereby application code is delivered in small, manageable pieces, independent of others.Their small scale and relative isolation can lead to many additional benefits, such as easier maintenance, improved productivity, greater fault tolerance, better business alignment, and more.

The distributed nature of microservices has challenges. To mitigate that following Spring Cloud features are used

  1. Service discovery : Eureka server
  2. API Gateway & load-balancing : Zuul
  3. Microservices communication: Feign

Containerization involves encapsulating or packaging up software code and all its dependencies so that it can run uniformly and consistently on any infrastructure. Docker one of the containerization platform is used to encapsulate each of the microservice in Docker container.

The Docker containers are then deployed on the AWS EC2 instances.

Use Case:

Consider there is a website where users can register themselves. Registered users can login to the website and opt-in to be a blood donor or can also post their blood requirement which will be emailed to all blood donors .

Application has the following three microservices

a. User Registration — will handle functionality like user registration, login authentication and persisting user details in DB

b. Blood Donor — Once the user has been registered he can opt to be blood donor . Once opted we will persist the user details as donor in DB. The user details are retrieved from User Registration microservices using feign client.

c. Blood Recipient — Registered user can post their blood requirement and the same will be emailed to all the users who opted as blood donor. The blood donor details are retrieved from Blood Donor microservices using feign client.

Application Architecture:

API Details:

Eureka Server : Discovery Service

Authentication and Authorization : Spring security + JWT

During login on successful authentication JWT token is created and sent to the client in response.

protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) throws IOException, ServletException {
String userName = ((User) auth.getPrincipal()).getUsername();
UserDTO userDetails = usersService.getUserDetailsByUserName(userName);
String token = Jwts.builder()
.setSubject(userDetails.getUserId())
.setExpiration(new Date(System.currentTimeMillis() + ```
Long.parseLong(environment.getProperty(“token.expiration_time”))))
.signWith(SignatureAlgorithm.HS512, ```
environment.getProperty(“token.secret”) )
.compact();
res.addHeader(“token”, token);
res.addHeader(“userId”, userDetails.getUserId());
}

To add spring security to the application we have added the spring security dependency to the pom xml. Once spring security dependency is added Spring boot application automatically requires basic authentication for all HTTP endpoints.

The WebSecurity class is annotated with @EnableWebSecurity to enable Spring Security’s web security support . It also extends WebSecurityConfigurerAdapter and overrides a couple of its methods to set some specifics of the web security configuration.

The configure(HttpSecurity) method defines which URL paths should be secured and which should not.Apart from Registration and login request all other request requires authentication .

@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final Environment environment;
@Autowired
public WebSecurity(Environment environment) {
this.environment = environment;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println(“in apigateway security”);
System.out.println(environment.getProperty(“api.registration.url.path”));
http.csrf().disable();
http.headers().frameOptions().disable();
http.authorizeRequests()
.antMatchers(HttpMethod.POST, 
environment.getProperty(“api.registration.url.path”)).permitAll()
.antMatchers(HttpMethod.POST, 
environment.getProperty(“api.login.url.path”)).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new AuthorizationFilter(authenticationManager(), environment));
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}

The authorization token sent in the request header is validated by extracting the token , parsing it to find userid . Once validated spring security context is prepared and forward the request to next filter in the filter chain.

@Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
String authorizationHeader = req.getHeader(environment.getProperty(“authorization.token.header.name”));
if (authorizationHeader == null || !authorizationHeader.startsWith(environment.getProperty(“authorization.token.header.prefix”))) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest req) {
String authorizationHeader = req.getHeader(environment.getProperty(“authorization.token.header.name”));
if (authorizationHeader == null) {
return null;
}
String token = authorizationHeader.replace(environment.getProperty(“authorization.token.header.prefix”), “”);
String userId = Jwts.parser()
.setSigningKey(environment.getProperty(“token.secret”))
.parseClaimsJws(token)
.getBody()
.getSubject();
if (userId == null) {
return null;
}
return new UsernamePasswordAuthenticationToken(userId, null, new ArrayList<>());
}

Docker image is built for each microservice and pushed to docker hub. In AWS EC2 we execute the docker run command which creates the docker container from the docker image present in docker hub and starts the container using the given command. Have used the public mysql docker image to create the DB for the three microservices.

Docker File:

from adoptopenjdk/openjdk11:latest
COPY target/user-registration-ws-0.0.1-SNAPSHOT.jar userws.jar
ENTRYPOINT [“java”,”-jar”,”userws.jar”]
mahendravarman.m@gmail.com

Recent Posts

Spring Webflux Functional Endpoint – File Upload

In this blog using the Spring WebFlux module, we are going to leverage the functional…

12 months ago

Serverless Functions with Spring Cloud Function, AWS Lambda

Spring Cloud Function is a project within the Spring ecosystem that allows developers to build…

12 months ago

Spring Boot + RabbitMQ – Decoupling Microservices Communication

RabbitMQ is an open-source message broker software that implements the Advanced Message Queuing Protocol (AMQP).…

1 year ago

Spring Integration – Sending files over SFTP

Spring Integration is a powerful extension of the Spring Framework designed to support the implementation…

1 year ago

Spring Cloud Config Client

The Spring Cloud Config Client is a component of the Spring Cloud framework that enables…

1 year ago

Handling CSV in Python

In Python, handling CSV (Comma Separated Values) files is easy using the built-in csv module.…

1 year ago