This is the 21st day of my participation in the August Text Challenge.More challenges in August

Blacklist Configuration

As the name suggests, is not accessible address. To implement a custom filter BlackListUrlFilter, you need to configure the blacklist address list blacklistUrl. Of course, other requirements can also implement custom filter rules.

spring:
  cloud:
    gateway:
      routes:
        # System module
        - id: demo-system
          uri: lb://demo-system
          predicates:
            - Path=/system/**
          filters:
            - StripPrefix=1
            - name: BlackListUrlFilter
              args:
                blacklistUrl:
                - /user/list
Copy the code

Whitelist Configuration

As the name suggests, this is the address that is allowed to access. And you don’t need to log in to access it. Set whites in ignore to allow anonymous access.

# whitelist is not checked
ignore:
  whites:
    - /auth/logout
    - /auth/login
    - /*/v2/api-docs
    - /csrf
Copy the code

Global filter

The global filter applies to all routes and does not need to be configured separately. We can use it to implement many unified business requirements, such as permission authentication, IP access restriction, and so on. The current unified gateway authentication AuthFilter. Java is the global filter used.

The separate definition only needs to implement the GlobalFilter, Ordered interfaces.

package com.demo.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/** * global filter ** /
@Component
public class AuthFilter implements GlobalFilter.Ordered
{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (null == token)
        {
            ServerHttpResponse response = exchange.getResponse();
            response.getHeaders().add("Content-Type"."application/json; charset=utf-8");
            String message = "{"message":"The request token information cannot be empty"}";
            DataBuffer buffer = response.bufferFactory().wrap(message.getBytes());
            return response.writeWith(Mono.just(buffer));
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder(a)
    {
        return 0; }}Copy the code

Sentinel current limiting is implemented

Sentinel supports stream limiting for mainstream API gateways such as Spring Cloud Gateway and Netflix Zuul.

1. Add dependencies

<! -- SpringCloud Alibaba Sentinel -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
		
<! -- SpringCloud Alibaba Sentinel Gateway -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
Copy the code

2. Traffic limiting rule configuration class

package com.demo.gateway.config;

import java.util.HashSet;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.demo.gateway.handler.SentinelFallbackHandler;

/** * Gateway traffic limiting configuration ** /
@Configuration
public class GatewayConfig
{
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelFallbackHandler sentinelGatewayExceptionHandler(a)
    {
        return new SentinelFallbackHandler();
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter(a)
    {
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit(a)
    {
        // Load the gateway traffic limiting rule
        initGatewayRules();
    }

    /** * Gateway traffic limiting rule */
    private void initGatewayRules(a)
    {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("demo-system")
                .setCount(3) // Traffic limiting threshold
                .setIntervalSec(60)); // Statistics time window, in seconds, default is 1 second
        // Load the gateway traffic limiting ruleGatewayRuleManager.loadRules(rules); }}Copy the code

3. Test and verify that traffic limiting is successful if an exception occurs when accessing system services for three times within one minute.

Sentinel packet current limiting

Configure traffic limiting for demo-system and Demo-Gen packets

1. Application. Yml configuration file

spring:
  cloud:
    gateway:
      routes:
        # System module
        - id: demo-system
          uri: lb://demo-system
          predicates:
            - Path=/system/**
          filters:
            - StripPrefix=1
        # Code generation
        - id: demo-gen
          uri: lb://demo-gen
          predicates:
            - Path=/code/**
          filters:
            - StripPrefix=1
Copy the code

2. Traffic limiting rule configuration class

package com.demo.gateway;

import java.util.HashSet;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.demo.gateway.handler.SentinelFallbackHandler;

/** * Gateway traffic limiting configuration ** /
@Configuration
public class GatewayConfig
{
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelFallbackHandler sentinelGatewayExceptionHandler(a)
    {
        return new SentinelFallbackHandler();
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter(a)
    {
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit(a)
    {
        // Load the gateway traffic limiting rule
        initGatewayRules();
    }

    /** * Gateway traffic limiting rule */
    private void initGatewayRules(a)
    {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("system-api")
                .setCount(3) // Traffic limiting threshold
                .setIntervalSec(60)); // Statistics time window, in seconds, default is 1 second
        rules.add(new GatewayFlowRule("code-api")
                .setCount(5) // Traffic limiting threshold
                .setIntervalSec(60));
        // Load the gateway traffic limiting rule
        GatewayRuleManager.loadRules(rules);
        // Load the traffic limiting group
        initCustomizedApis();
    }

    /** * Traffic limiting group */
    private void initCustomizedApis(a)
    {
        Set<ApiDefinition> definitions = new HashSet<>();
        / / the demo - system group
        ApiDefinition api1 = new ApiDefinition("system-api").setPredicateItems(new HashSet<ApiPredicateItem>()
        {
            private static final long serialVersionUID = 1L;
            {
                // Matches all requests from /user and its subpath
                add(new ApiPathPredicateItem().setPattern("/system/user/**") .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); }});/ / the demo - gen group
        ApiDefinition api2 = new ApiDefinition("code-api").setPredicateItems(new HashSet<ApiPredicateItem>()
        {
            private static final long serialVersionUID = 1L;
            {
                // Matches only /job/list
                add(new ApiPathPredicateItem().setPattern("/code/gen/list")); }}); definitions.add(api1); definitions.add(api2);// Load the traffic limiting groupGatewayApiDefinitionManager.loadApiDefinitions(definitions); }}Copy the code

Visit: http://localhost:8080/system/user/list (trigger current limiting access: http://localhost:8080/system/role/list (not trigger current limiting access: http://localhost:8080/code/gen/list (trigger current limiting access: http://localhost:8080/code/gen/xxxx (not trigger current limit)

[#]Sentinel Custom exception

Sentinel supports custom exception handling in order to show more user-friendly traffic limiting cues.

Solution 1: YML configuration

# Spring Spring: cloud: sentinel: SCG: fallback: mode: response Response-body: '{"code":403," MSG ":" Request exceeded the maximum number, please try again later "}'Copy the code

Scheme 2: GatewayConfig injection Bean

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelFallbackHandler sentinelGatewayExceptionHandler()
{
	return new SentinelFallbackHandler();
}
Copy the code

SentinelFallbackHandler.java

package com.demo.gateway.handler;

import java.nio.charset.StandardCharsets;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

/** * Custom traffic limiting exception handling ** /
public class SentinelFallbackHandler implements WebExceptionHandler
{
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange)
    {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.getHeaders().add("Content-Type"."application/json; charset=UTF-8");
        byte[] datas = "{"code": 429,"msg":"The request exceeded the maximum number, please try again later"}".getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);
        return serverHttpResponse.writeWith(Mono.just(buffer));
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
    {
        if (exchange.getResponse().isCommitted())
        {
            return Mono.error(ex);
        }
        if(! BlockException.isBlockException(ex)) {return Mono.error(ex);
        }
        return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange));
    }

    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable)
    {
        returnGatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); }}Copy the code