在业务开发的时候,经常会遇到某一个接口不能对外暴露,只能内网服务间调用的实际需求。面对这样的情况,我们该如何实现呢?今天,我们就来理一理这个问题,从几个可行的方案中,挑选一个来实现。
1. 内外网接口微服务隔离
将对外暴露的接口和对内暴露的接口分别放到两个微服务上,一个服务里所有的接口均对外暴露,另一个服务的接口只能内网服务间调用。
该方案需要额外编写一个只对内部暴露接口的微服务,将所有只能对内暴露的业务接口聚合到这个微服务里,通过这个聚合的微服务,分别去各个业务侧获取资源。
该方案,新增一个微服务做请求转发,增加了系统的复杂性,增大了调用耗时以及后期的维护成本。
2. 网关 + redis 实现白名单机制
在 redis 里维护一套接口白名单列表,外部请求到达网关时,从 redis 获取接口白名单,在白名单内的接口放行,反之拒绝掉。
该方案的好处是,对业务代码零侵入,只需要维护好白名单列表即可;
不足之处在于,白名单的维护是一个持续性投入的工作,在很多公司,业务开发无法直接触及到 redis,只能提工单申请,增加了开发成本;另外,每次请求进来,都需要判断白名单,增加了系统响应耗时,考虑到正常情况下外部进来的请求大部分都是在白名单内的,只有极少数恶意请求才会被白名单机制所拦截,所以该方案的性价比很低。
3. 方案三 网关 + aop
相比于方案二对接口进行白名单判断而言,方案三是对请求来源进行判断,并将该判断下沉到业务侧。避免了网关侧的逻辑判断,从而提升系统响应速度。
我们知道,外部进来的请求一定会经过网关再被分发到具体的业务侧,内部服务间的调用是不用走外部网关的(走 k8s 的 service)。
根据这个特点,我们可以对所有经过网关的请求的header里添加一个字段,业务侧接口收到请求后,判断header里是否有该字段,如果有,则说明该请求来自外部,没有,则属于内部服务的调用,再根据该接口是否属于内部接口来决定是否放行该请求。
该方案将内外网访问权限的处理分布到各个业务侧进行,消除了由网关来处理的系统性瓶颈;同时,开发者可以在业务侧直接确定接口的内外网访问权限,提升开发效率的同时,增加了代码的可读性。
当然该方案会对业务代码有一定的侵入性,不过可以通过注解的形式,最大限度的降低这种侵入性。
具体实操
下面就方案三,进行具体的代码演示。
首先在网关侧,需要对进来的请求header添加外网标识符: from=public
@componentpublic class authfilter implements globalfilter, ordered { @override public mono filter ( serverwebexchange exchange, gatewayfilterchain chain ) { return chain.filter( exchange.mutate().request( exchange.getrequest().mutate().header(id, ).header(from, public).build()) .build() ); } @override public int getorder () { return 0; } } 接着,编写内外网访问权限判断的aop和注解
@aspect@component@slf4jpublic class onlyintranetaccessaspect { @pointcut ( @within(org.openmmlab.platform.common.annotation.onlyintranetaccess) ) public void onlyintranetaccessonclass () {} @pointcut ( @annotation(org.openmmlab.platform.common.annotation.onlyintranetaccess) ) public void onlyintranetaccessonmethed () { } @before ( value = onlyintranetaccessonmethed() || onlyintranetaccessonclass() ) public void before () { httpservletrequest hsr = (( servletrequestattributes ) requestcontextholder.getrequestattributes()) .getrequest (); string from = hsr.getheader ( from ); if ( !stringutils.isempty( from ) && public.equals ( from )) { log.error ( this api is only allowed invoked by intranet source ); throw new mmexception ( returnenum.c_network_internet_access_not_allowed_error); } } }@target({elementtype.method})@retention(retentionpolicy.runtime)@documentedpublic @interface onlyintranetaccess {} 最后,在只能内网访问的接口上加上@onlyintranetaccess注解即可
罗姆:凭SiC拿下电动方程式大赛,逆变器减小30%
华为mate10什么时候上市?华为mate10最新消息:华为mate10提前发布,拯救P10,给予友商致命一击
软银首席执行官孙正义的AI“帝国”!
8K电视在彩电市场将如何发展?
关于三星生物处理器的性能分析和应用
接口不能对外暴露怎么办?
2018年USB PD快充市场涨幅达600% 中国企业占五成!
要闻:苹果向更换电池用户退款50美元 高通在京成立人工智能研究部门
系留无人机系统在波尔多竞技场提供安全保障
LED显示屏厂商:全面奋战一线市场,锁定用户范围
美国移动运营商U.S. Cellular已授予三星电子一份商业合同
LED照明与CFL节能灯照明的市场对比与前景
虚拟现实头显产品竞争激烈,那么哪款是最好的呢?
引用数据类型的概念_引用数据类型有哪几种
非洲猪瘟检测设备可靠吗以及功能介绍
iphone13mini值得买吗
澳大利亚1.2GW森林风电项目获批,首阶段预计将于2023年底投入运营
全国半导体物理学术会议在浙江杭州成功举行
硬件比拼放缓:大牌厂商等何去何从?
单片机最小系统的组成部分 使用proteus软件搭建最小单片机系统的操作方法