Backend Development 28 min read

Implementing a Spring Cloud Gateway with Rate Limiting, BCrypt Encryption, and JWT Authentication

This guide demonstrates how to build a Spring Cloud Gateway for microservices, covering system setup, CORS handling, rate‑limiting with the token‑bucket algorithm, password hashing with BCrypt, and secure JWT‑based authentication, complete with Maven dependencies, configuration files, and filter implementations.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Implementing a Spring Cloud Gateway with Rate Limiting, BCrypt Encryption, and JWT Authentication

Objectives

Master the construction of a microservice gateway, implement gateway rate limiting, use BCrypt for password encryption and verification, understand encryption algorithms, and apply JWT for microservice authentication.

1. Microservice Gateway Overview

Direct client calls to multiple microservices cause complexity, cross‑origin issues, duplicated authentication, and difficulty in refactoring. A gateway solves these problems by acting as a middle layer that handles security, performance, and monitoring.

Typical architecture:

Advantages include security (services hidden behind the gateway), easy monitoring, centralized authentication, reduced client‑service interactions, and unified authorization.

1.1 Gateway Technologies

nginx – high‑performance HTTP and reverse proxy server.

Zuul – Netflix JVM‑based router and load balancer.

Spring Cloud Gateway – Spring‑based gateway with circuit breaker, path rewrite, and better performance than Zuul.

1.2 Building the Gateway Service

Create a Maven module changgou_gateway_system with the following dependencies:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Define the main class:

@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

Add application.yml with routes, CORS configuration, and server settings:

spring:
  application:
    name: sysgateway
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods:
            - GET
            - POST
            - PUT
            - DELETE
      routes:
      - id: goods
        uri: lb://goods
        predicates:
        - Path=/goods/**
        filters:
        - StripPrefix=1
      - id: system
        uri: lb://system
        predicates:
        - Path=/system/**
        filters:
        - StripPrefix=1
server:
  port: 9101
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true

1.3 CORS Configuration

Extend application.yml with the globalcors section shown above to allow all origins and HTTP methods.

1.4 Gateway Filters

Two example filters demonstrate request logging and IP/URL inspection.

@Component
public class IpFilter implements GlobalFilter, Ordered {
    @Override
    public Mono
filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("经过第1个过滤器IpFilter");
        InetSocketAddress remote = exchange.getRequest().getRemoteAddress();
        System.out.println("ip:" + remote.getHostName());
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() { return 1; }
}

@Component
public class UrlFilter implements GlobalFilter, Ordered {
    @Override
    public Mono
filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("经过第2个过滤器UrlFilter");
        String url = exchange.getRequest().getURI().getPath();
        System.out.println("url:" + url);
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() { return 2; }
}

2. Gateway Rate Limiting

Implement per‑IP rate limiting (1 request per second) using Spring Cloud Gateway's built‑in RequestRateLimiter backed by Redis.

2.1 Token Bucket Algorithm

The token bucket controls request flow by adding tokens at a fixed rate, limiting the bucket size, and requiring a token for each request.

2.2 Configuration

Add Redis dependency:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
  <version>2.1.3.RELEASE</version>
</dependency>

Define a KeyResolver bean to use the client IP as the rate‑limit key:

@Bean
public KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}

Update application.yml to include the RequestRateLimiter filter:

filters:
- name: RequestRateLimiter
  args:
    key-resolver: "#{@ipKeyResolver}"
    redis-rate-limiter.replenishRate: 1
    redis-rate-limiter.burstCapacity: 1

When the limit is exceeded, the gateway returns HTTP 429.

3. BCrypt Password Encryption

BCrypt provides a strong, salted hash for storing passwords.

3.1 Quick Start

String gensalt = BCrypt.gensalt();
String hash = BCrypt.hashpw("123456", gensalt);
System.out.println(hash);

boolean match = BCrypt.checkpw("123456", hash);
System.out.println(match);

3.2 Integrating into Admin Service

Encrypt passwords before persisting:

public void add(Admin admin) {
    String password = BCrypt.hashpw(admin.getPassword(), BCrypt.gensalt());
    admin.setPassword(password);
    adminMapper.insert(admin);
}

Validate login credentials:

public boolean login(Admin admin) {
    Admin stored = adminMapper.selectOneByLoginName(admin.getLoginName());
    if (stored == null) return false;
    return BCrypt.checkpw(admin.getPassword(), stored.getPassword());
}

4. Encryption Algorithms Overview

Brief comparison of reversible (symmetric, asymmetric) and irreversible (hash) algorithms, including AES, RSA, MD5, SHA, and Base64 encoding.

5. JWT for Microservice Authentication

JWT enables stateless, token‑based authentication across microservices.

5.1 Token Structure

Header (algorithm, type), Payload (claims such as iss, sub, exp, etc.), and Signature (header + payload signed with a secret).

5.2 Creating JWT with JJWT

Add JJWT dependency:

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.0</version>
</dependency>

Utility class to generate tokens:

public class JwtUtil {
    public static final Long JWT_TTL = 3600000L; // 1 hour
    public static final String JWT_KEY = "itcast";
    public static String createJWT(String id, String subject, Long ttlMillis) {
        SignatureAlgorithm alg = SignatureAlgorithm.HS256;
        long now = System.currentTimeMillis();
        Date exp = new Date(now + (ttlMillis != null ? ttlMillis : JWT_TTL));
        SecretKey key = generalKey();
        return Jwts.builder()
                .setId(id)
                .setSubject(subject)
                .setIssuer("admin")
                .setIssuedAt(new Date(now))
                .setExpiration(exp)
                .signWith(alg, key)
                .compact();
    }
    private static SecretKey generalKey() {
        byte[] encoded = Base64.getDecoder().decode(JWT_KEY);
        return new SecretKeySpec(encoded, 0, encoded.length, "AES");
    }
}

Login endpoint returns a token on successful authentication:

@PostMapping("/login")
public Result login(@RequestBody Admin admin) {
    if (adminService.login(admin)) {
        Map
info = new HashMap<>();
        info.put("username", admin.getLoginName());
        String token = JwtUtil.createJWT(UUID.randomUUID().toString(), admin.getLoginName(), null);
        info.put("token", token);
        return new Result(true, StatusCode.OK, "登录成功", info);
    }
    return new Result(false, StatusCode.LOGINERROR, "用户名或密码错误");
}

5.3 Gateway JWT Validation Filter

Add JJWT dependency to the gateway and create a utility for parsing tokens:

public class JwtUtil {
    public static final String JWT_KEY = "itcast";
    public static SecretKey generalKey() {
        byte[] encoded = Base64.getDecoder().decode(JWT_KEY);
        return new SecretKeySpec(encoded, 0, encoded.length, "AES");
    }
    public static Claims parseJWT(String jwt) throws Exception {
        return Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(jwt).getBody();
    }
}

Global filter that checks the token header, allows the login path, and returns HTTP 401 for missing or invalid tokens:

@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    private static final String AUTHORIZE_TOKEN = "token";
    @Override
    public Mono
filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        if (request.getURI().getPath().contains("/admin/login")) {
            return chain.filter(exchange);
        }
        String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN);
        if (StringUtils.isEmpty(token)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        try {
            JwtUtil.parseJWT(token);
        } catch (Exception e) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() { return 0; }
}

Testing with Postman shows that requests without a token receive 401, while requests with a valid JWT return the expected data.

Source: blog.csdn.net/qq_36079912/article/details/104831199

MicroservicesSpring BootsecurityRate LimitingJWTSpring Cloud Gatewaybcrypt
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.