1、RemoteAddr断言

1.1 源码解析

## RemoteAddrRoutePredicateFactory类
public Predicate<ServerWebExchange> apply(RemoteAddrRoutePredicateFactory.Config config) {//获取yml配置的地址信息,如下图获取的到地址是192.168.21.21final List<IpSubnetFilterRule> sources = this.convert(config.sources);return new GatewayPredicate() {public boolean test(ServerWebExchange exchange) {//获取请求的地址(执行的代码就是下面那一个方法) 如下图获取到的是192.168.21.100InetSocketAddress remoteAddress = config.remoteAddressResolver.resolve(exchange);if (remoteAddress != null && remoteAddress.getAddress() != null) {String hostAddress = remoteAddress.getAddress().getHostAddress();String host = exchange.getRequest().getURI().getHost();if (RemoteAddrRoutePredicateFactory.log.isDebugEnabled() && !hostAddress.equals(host)) {RemoteAddrRoutePredicateFactory.log.debug("Remote addresses didn't match " + hostAddress + " != " + host);}Iterator var5 = sources.iterator();while(var5.hasNext()) {IpSubnetFilterRule source = (IpSubnetFilterRule)var5.next();//通过正则匹配判断是否通过if (source.matches(remoteAddress)) {return true;}}}return false;}public Object getConfig() {return config;}public String toString() {return String.format("RemoteAddrs: %s", config.getSources());}};
}## RemoteAddressResolver类
default InetSocketAddress resolve(ServerWebExchange exchange) {//获取直接连接网关的IP地址,如果通nginx转发到网关的,那么这里获取到的是nginx的IP地址。return exchange.getRequest().getRemoteAddress();
}

yml配置:

如果我们在yml的断言配置如下图,那么他将匹配不成功

2、XForwardedRemoteAddr断言

2.1 源码解析

## XForwardedRemoteAddrRoutePredicateFactory类
public Predicate<ServerWebExchange> apply(XForwardedRemoteAddrRoutePredicateFactory.Config config) {if (log.isDebugEnabled()) {log.debug("Applying XForwardedRemoteAddr route predicate with maxTrustedIndex of " + config.getMaxTrustedIndex() + " for " + config.getSources().size() + " source(s)");}org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory.Config wrappedConfig = new org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory.Config();/*** 获取yml配置的IP地址信息,将从获取yml配置的IP地址信息传递* 给RemoteAddrRoutePredicateFactory,如下图获取的到地址是192.168.21.21*/wrappedConfig.setSources(config.getSources());/*** config.getMaxTrustedIndex() 默认值为 1* XForwardedRemoteAddressResolver重新了resolve这个方法,用来获取请求头中X-Forwarded-For的值*/wrappedConfig.setRemoteAddressResolver(XForwardedRemoteAddressResolver.maxTrustedIndex(config.getMaxTrustedIndex()));//说明RemoteAddrRoutePredicateFactory底层还是用RemoteAddr断言的规则RemoteAddrRoutePredicateFactory remoteAddrRoutePredicateFactory = new RemoteAddrRoutePredicateFactory();//将封装好的config传递给RemoteAddrRoutePredicateFactoryPredicate<ServerWebExchange> wrappedPredicate = remoteAddrRoutePredicateFactory.apply(wrappedConfig);return (exchange) -> {Boolean isAllowed = wrappedPredicate.test(exchange);if (log.isDebugEnabled()) {ServerHttpRequest request = exchange.getRequest();log.debug("Request for \"" + request.getURI() + "\" from client \"" + request.getRemoteAddress().getAddress().getHostAddress() + "\" with \"" + "X-Forwarded-For" + "\" header value of \"" + request.getHeaders().get("X-Forwarded-For") + "\" is " + (isAllowed ? "ALLOWED" : "NOT ALLOWED"));}return isAllowed;};
}## RemoteAddrRoutePredicateFactory类
public Predicate<ServerWebExchange> apply(RemoteAddrRoutePredicateFactory.Config config) {//获取传递过来的IP地址,如下图获取的到地址是192.168.21.21final List<IpSubnetFilterRule> sources = this.convert(config.sources);return new GatewayPredicate() {public boolean test(ServerWebExchange exchange) {//获取请求的地址(执行的代码就是下面那一个方法) 如下图获取到的是192.168.21.22InetSocketAddress remoteAddress = config.remoteAddressResolver.resolve(exchange);if (remoteAddress != null && remoteAddress.getAddress() != null) {String hostAddress = remoteAddress.getAddress().getHostAddress();String host = exchange.getRequest().getURI().getHost();if (RemoteAddrRoutePredicateFactory.log.isDebugEnabled() && !hostAddress.equals(host)) {RemoteAddrRoutePredicateFactory.log.debug("Remote addresses didn't match " + hostAddress + " != " + host);}Iterator var5 = sources.iterator();while(var5.hasNext()) {IpSubnetFilterRule source = (IpSubnetFilterRule)var5.next();//通过正则匹配判断是否通过if (source.matches(remoteAddress)) {return true;}}}return false;}...};
}## XForwardedRemoteAddressResolver类
public InetSocketAddress resolve(ServerWebExchange exchange) {//获取请求头中X-Forwarded-For的值List<String> xForwardedValues = this.extractXForwardedValues(exchange);Collections.reverse(xForwardedValues);if (!xForwardedValues.isEmpty()) {//获取指定位置的IP,int index = Math.min(xForwardedValues.size(), this.maxTrustedIndex) - 1;return new InetSocketAddress((String)xForwardedValues.get(index), 0);} else {return this.defaultRemoteIpResolver.resolve(exchange);}
}## XForwardedRemoteAddressResolver类
private List<String> extractXForwardedValues(ServerWebExchange exchange) {List<String> xForwardedValues = exchange.getRequest().getHeaders().get("X-Forwarded-For");if (xForwardedValues != null && !xForwardedValues.isEmpty()) {//如果X-Forwarded-For的值多个直接丢弃if (xForwardedValues.size() > 1) {log.warn("Multiple X-Forwarded-For headers found, discarding all");return Collections.emptyList();} else {List<String> values = Arrays.asList(((String)xForwardedValues.get(0)).split(", "));return values.size() == 1 && !StringUtils.hasText((String)values.get(0)) ? Collections.emptyList() : values;}} else {return Collections.emptyList();}
}

config.getMaxTrustedIndex()的默认值为1,所以请求头X-Forwarded-For值的最后一个值,如下图,获取的值为192.168.21.22。

如果我们在yml的断言配置如下图,那么他将匹配不成功。

XForwardedRemoteAddressResolver有两个静态构造函数方法,它们采用不同的安全方法:

  • XForwardedRemoteAddressResolver::trustAllRemoteAddressResolver返回始终采用标头中找到的第一个 IP 地址的a X-Forwarded-For。这种方法容易受到欺骗,因为恶意客户端可以为 设置一个初始值X-Forwarded-For,解析器会接受该值。

  • XForwardedRemoteAddressResolver::maxTrustedIndex采用与在 Spring Cloud Gateway 前面运行的可信基础设施数量相关的索引。例如,如果 Spring Cloud Gateway 只能通过 HAProxy 访问,则应使用值 1。如果在访问 Spring Cloud Gateway 之前需要两跳可信基础设施,则应使用值 2。

maxTrustedIndex值怎么设置没还有解决

Gateway的RemoteAddr与RemoteAddressResolver源码分析相关推荐

  1. Spark RPC框架源码分析(二)RPC运行时序

    前情提要: Spark RPC框架源码分析(一)简述 一. Spark RPC概述 上一篇我们已经说明了Spark RPC框架的一个简单例子,Spark RPC相关的两个编程模型,Actor模型和Re ...

  2. Docker源码分析(八):Docker Container网络(下)

    http://www.infoq.com/cn/articles/docker-source-code-analysis-part8 1.Docker Client配置容器网络模式 Docker目前支 ...

  3. Istio Pilot 源码分析(一)

    张海东, ‍多点生活(成都)云原生开发工程师. Istio 作为目前 Servic Mesh 方案中的翘楚,吸引着越来越多的企业及开发者.越来越多的团队想将其应用于微服务的治理,但在实际落地时却因为不 ...

  4. 源码分析RocketMQ ACL实现机制

    有关RocketMQ ACL的使用请查看上一篇<RocketMQ ACL使用指南>,本文从源码的角度,分析一下RocketMQ ACL的实现原理. 备注:RocketMQ在4.4.0时引入 ...

  5. grpc-go客户端源码分析

    grpc-go客户端源码分析 代码讲解基于v1.37.0版本. 和grpc-go服务端源码分析一样,我们先看一段示例代码, const (address = "localhost:50051 ...

  6. LWIP源码分析——ip4.c

    LWIP源码分析--ip4.c ipv4是IP栈中重要的一部分,实现功能使用了上千行代码,分析起来可能会稍显复杂,这部分采用的分析的思路是,重点思想总结部分放在前面,剩下的结合代码穿插分析 1.ipv ...

  7. Kafka源码分析10:副本状态机ReplicaStateMachine详解 (图解+秒懂+史上最全)

    文章很长,建议收藏起来,慢慢读! Java 高并发 发烧友社群:疯狂创客圈 奉上以下珍贵的学习资源: 免费赠送 经典图书:<Java高并发核心编程(卷1)> 面试必备 + 大厂必备 +涨薪 ...

  8. Flask源码分析(一)

    知识背景 Flask是python web框架,主要包含werkzeug和jinja2,前者是一个WSGI工具集,后者用来实现模板处理. WSGI,Werkzeug WSGI WSGI(Web Ser ...

  9. RuoYi-Vue-Plus 与 RuoYi-Cloud-Plus 高端进阶 源码分析 系列教程

    专栏地址 由项目成员 MichelleChung 书写 vue版本专栏 https://blog.csdn.net/michelle_zhong/category_11109741.html Clou ...

最新文章

  1. java命名course为名的class_Java教程之变量命名
  2. ie浏览器中 overflow:hidden无作用的解决方案
  3. vue调用接口获取后台数据_Vuex 存储||获取后台接口数据
  4. 零基础学Python(第七章 while循环)
  5. 20220213-CTF MISC-a_good_idea(stegsolve工具的使用)-2017_Dating_in_Singapore
  6. go 默认http版本_【每日一库】超赞的 Go 语言 INI 文件操作
  7. 如何在 Kubernetes Pod 内进行网络抓包
  8. non thread safe php vc11,PHP 中什么线程安全(TS)和非线程安全(NTS)
  9. cusparseScsrsv_analysis函数导致内存暴涨问题
  10. 逆天语言模型GPT-2最新开源:345M预训练模型和1.5B参数都来了
  11. matlab的三维数组(三维矩阵)
  12. scala 提取器模式匹配_Scala提取器应用,取消应用和模式匹配
  13. DevExpress 之 GridControl 自定义列
  14. axios 跨域传参_axios跨域问题
  15. (转)星巴克其实是靠大数据盈利的!
  16. Struts框架详解
  17. iso 开发学习--简易音乐播放器(基于iPhone4s屏幕尺寸)
  18. filezilla提示 local: unable to open
  19. python xlwings excel 根据列排序
  20. 全球竞争力报告全部数据(2006-2019年)

热门文章

  1. 全球与中国外科工作服市场深度研究分析报告
  2. 计算机桌面图标怎样变大变小,桌面图标怎么变小,小编告诉你电脑桌面图标的太大怎么调小...
  3. Hello, Lucene
  4. el-calendar尺寸修改
  5. 英国武装部队启动首个专用网络军团
  6. ps4命运2老是断开服务器无响应,《命运2》进不去是什么原因 进不去原因介绍
  7. mysql mongodb 秒杀_绝赞!B站投币20W+的Redis/MongoDB/Mysql性能优化宝藏库,我先磕了
  8. Sublime Text3提示PyV8相关的错误
  9. 如何查看SLIC 2.1
  10. 基于Jackson的JSON工具类封装 JsonUtils