新站突然网站停止收录,怎么和网站建设公司签合同,徐州百姓网,做php网站会员开店代码如何编写文章目录 前言一、内置路由断言1. 案例#xff08;Weight#xff09;2. 更多断言 二、自定义路由断言1. 黑名单断言2. 全局异常处理3. 应用配置4. 单元测试 总结 前言
Spring Cloud Gateway可以让我们根据请求内容精确匹配到对应路由服务,官方已经内置了很多路由断言,我们也… 文章目录 前言一、内置路由断言1. 案例Weight2. 更多断言 二、自定义路由断言1. 黑名单断言2. 全局异常处理3. 应用配置4. 单元测试 总结 前言
Spring Cloud Gateway可以让我们根据请求内容精确匹配到对应路由服务,官方已经内置了很多路由断言,我们也可以根据需求自己定义,RemoteAddrRoutePredicateFactory就像是根据IP去匹配的白名单,接下来我们根据它来自定义一个IP黑名单。 一、内置路由断言
1. 案例Weight
spring:cloud:gateway:routes:- id: weight_highuri: https://weighthigh.orgpredicates:- Weightgroup1, 8- id: weight_lowuri: https://weightlow.orgpredicates:- Weightgroup1, 2这条路线将把约80%的流量转发到weighthigh.org约20%的流量转发给weighlow.org 2. 更多断言
序号断言类型用法描述1After- After2017-01-20T17:42:47.789-07:00[America/Denver]此路由与2017年1月20日17:42:47之后的任何请求相匹配。2Before- Before2017-01-20T17:42:47.789-07:00[America/Denver]此路由与2017年1月20日17:42:47之前的任何请求相匹配。3Between- Between2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]此路由与2017年1月20日17:42:47之后至2017年1月21日17:42:47之前提出的任何请求相匹配。4Cookie- Cookiechocolate, ch.p此路由匹配名为chocolate的cookie的请求该cookie的值与ch.p匹配。5Header- HeaderX-Request-Id, \d此路由匹配请求有一个名为X-request-Id的请求头其值与\d正则表达式匹配即它有一个或多个数字的值。6Host- Host.somehost.org,.anotherhost.org此路由匹配请求的Host值为www.somehost.org、beta.somehost.org或www.anotherhost.org。7Method- MethodGET,POST此路由匹配请求方法是GET或POST。8Path- Path/red/{segment},/blue/{segment}此路由匹配请求路径为/red/1 或 /red/1/ 或 /red/blue 或/blue/green。9Query- Querygreen- Querygreen - Queryred, gree.10RemoteAddr- RemoteAddr192.168.1.1/24如果请求的远程地址是192.168.1.10则此路由匹配。11XForwarded Remote Addr- XForwardedRemoteAddr192.168.1.1/24如果X-Forwarded-For标头包含例如192.168.1.10则此路由匹配。
二、自定义路由断言
1. 黑名单断言
package org.example.gateway.predicate;import io.netty.handler.ipfilter.IpFilterRuleType;
import io.netty.handler.ipfilter.IpSubnetFilterRule;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.cloud.gateway.support.ipresolver.RemoteAddressResolver;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import static org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType.GATHER_LIST;/*** Create by zjg on 2024/7/29*/
Component
public class BlackRemoteAddrRoutePredicateFactory extends AbstractRoutePredicateFactoryBlackRemoteAddrRoutePredicateFactory.Config {private static final Log log LogFactory.getLog(BlackRemoteAddrRoutePredicateFactory.class);public BlackRemoteAddrRoutePredicateFactory() {super(BlackRemoteAddrRoutePredicateFactory.Config.class);}Overridepublic ShortcutType shortcutType() {return GATHER_LIST;}Overridepublic ListString shortcutFieldOrder() {return Collections.singletonList(sources);}NotNullprivate ListIpSubnetFilterRule convert(ListString values) {ListIpSubnetFilterRule sources new ArrayList();for (String arg : values) {addSource(sources, arg);}return sources;}Overridepublic PredicateServerWebExchange apply(BlackRemoteAddrRoutePredicateFactory.Config config) {ListIpSubnetFilterRule sources convert(config.sources);return new GatewayPredicate() {Overridepublic boolean test(ServerWebExchange exchange) {InetSocketAddress remoteAddress config.remoteAddressResolver.resolve(exchange);if (remoteAddress ! null remoteAddress.getAddress() ! null) {String hostAddress remoteAddress.getAddress().getHostAddress();String host exchange.getRequest().getURI().getHost();if (log.isDebugEnabled() !hostAddress.equals(host)) {log.debug(Black remote addresses didnt match hostAddress ! host);}for (IpSubnetFilterRule source : sources) {if (source.matches(remoteAddress)) {exchange.getAttributes().put(BlackRemoteAddrRoutePredicateFactory,remoteAddress.getAddress().getHostAddress());return false;//能匹配到则在黑名单中,不再执行}}}return true;}Overridepublic Object getConfig() {return config;}Overridepublic String toString() {return String.format(BlackRemoteAddrs: %s, config.getSources());}};}private void addSource(ListIpSubnetFilterRule sources, String source) {if (!source.contains(/)) { // no netmask, add defaultsource source /32;}String[] ipAddressCidrPrefix source.split(/, 2);String ipAddress ipAddressCidrPrefix[0];int cidrPrefix Integer.parseInt(ipAddressCidrPrefix[1]);sources.add(new IpSubnetFilterRule(ipAddress, cidrPrefix, IpFilterRuleType.ACCEPT));}Validatedpublic static class Config {NotEmptyprivate ListString sources new ArrayList();NotNullprivate RemoteAddressResolver remoteAddressResolver new RemoteAddressResolver() {};public ListString getSources() {return sources;}public BlackRemoteAddrRoutePredicateFactory.Config setSources(ListString sources) {this.sources sources;return this;}public BlackRemoteAddrRoutePredicateFactory.Config setSources(String... sources) {this.sources Arrays.asList(sources);return this;}public BlackRemoteAddrRoutePredicateFactory.Config setRemoteAddressResolver(RemoteAddressResolver remoteAddressResolver) {this.remoteAddressResolver remoteAddressResolver;return this;}}
}2. 全局异常处理
package org.example.gateway.config;import org.example.common.model.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.reactive.resource.NoResourceFoundException;
import org.springframework.web.server.ServerWebExchange;
import java.io.PrintWriter;
import java.io.StringWriter;/*** Create by zjg on 2024/7/29*/
RestControllerAdvice
public class GlobalExceptionHandler {Logger logger LoggerFactory.getLogger(GlobalExceptionHandler.class);ExceptionHandler(NoResourceFoundException.class)//无可用路由public Result exception(ServerWebExchange exchange, NoResourceFoundException ex){String detail ex.getBody().getDetail();String markresource ;String message detail.substring(detail.indexOf(mark) mark.length());setStatusCode(exchange.getResponse(),ex.getStatusCode());if(StringUtils.hasText(exchange.getAttribute(BlackRemoteAddrRoutePredicateFactory))){//IP黑名单return Result.error(ex.getStatusCode().value(),拒绝访问,您的IP已被添加到黑名单中,拒绝访问!);}return Result.error(ex.getStatusCode().value(),无可用路由,String.format(没有可用的路由[%s],message));}ExceptionHandler(NotFoundException.class)//无可用服务public Result exception(ServerHttpResponse response,NotFoundException ex){logger.error(ex.getMessage());String detail ex.getBody().getDetail();String markfor ;String message detail.substring(detail.indexOf(mark) mark.length());setStatusCode(response,ex.getStatusCode());return Result.error(ex.getStatusCode().value(),服务不可用,String.format(没有可用的服务实例[%s],message));}ExceptionHandler(Exception.class)//异常保底public Result exception(ServerHttpResponse response,Exception exception){StringWriter stringWriter new StringWriter();PrintWriter writernew PrintWriter(stringWriter);exception.printStackTrace(writer);logger.error(stringWriter.toString());setStatusCode(response,HttpStatus.INTERNAL_SERVER_ERROR);return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(),exception.getMessage());}private void setStatusCode(ServerHttpResponse response,HttpStatusCode httpStatusCode){response.setStatusCode(httpStatusCode);}
}3. 应用配置
spring:cloud:gateway:routes:- id: provider-serviceuri: lb://provider-servicepredicates:- Path/provider/**- BlackRemoteAddr192.168.1.1/24,127.0.0.14. 单元测试
curl 192.168.0.104:8888/provider/hello正常访问
黑名单访问 总结
回到顶部 这样我们就能通过断言配置黑名单可以针对固定IP做灵活处理。