在业务开发的时候,常常会遇到某一个接口不能对外裸露,只能内网服务间调用的理论需要。面对这样的状况,咱们该如何实现呢?

明天,咱们就来理一理这个问题,从几个可行的计划中,筛选一个来实现。

举荐一个开源收费的 Spring Boot 实战我的项目:

https://github.com/javastacks/spring-boot-best-practice

1. 内外网接口微服务隔离

将对外裸露的接口和对内裸露的接口别离放到两个微服务上,一个服务里所有的接口均对外裸露,另一个服务的接口只能内网服务间调用。

该计划须要额定编写一个只对外部裸露接口的微服务,将所有只能对内裸露的业务接口聚合到这个微服务里,通过这个聚合的微服务,别离去各个业务侧获取资源。

该计划,新增一个微服务做申请转发,减少了零碎的复杂性,增大了调用耗时以及前期的保护老本。

2. 网关 + redis 实现白名单机制

在 redis 里保护一套接口白名单列表,内部申请达到网关时,从 redis 获取接口白名单,在白名单内的接口放行,反之回绝掉。

该计划的益处是,对业务代码零侵入,只须要保护好白名单列表即可;

不足之处在于,白名单的保护是一个持续性投入的工作,在很多公司,业务开发无奈间接涉及到 redis,只能提工单申请,减少了开发成本;另外,每次申请进来,都须要判断白名单,减少了零碎响应耗时,思考到失常状况下内部进来的申请大部分都是在白名单内的,只有极少数歹意申请才会被白名单机制所拦挡,所以该计划的性价比很低。

3. 计划三 网关 + AOP

相比于计划二对接口进行白名单判断而言,计划三是对申请起源进行判断,并将该判断下沉到业务侧。防止了网关侧的逻辑判断,从而晋升零碎响应速度。

咱们晓得,内部进来的申请肯定会通过网关再被散发到具体的业务侧,外部服务间的调用是不必走内部网关的(走 k8s 的 service)。

依据这个特点,咱们能够对所有通过网关的申请的header里增加一个字段,业务侧接口收到申请后,判断header里是否有该字段,如果有,则阐明该申请来自内部,没有,则属于外部服务的调用,再依据该接口是否属于外部接口来决定是否放行该申请。

该计划将内外网拜访权限的解决散布到各个业务侧进行,打消了由网关来解决的系统性瓶颈;同时,开发者能够在业务侧间接确定接口的内外网拜访权限,晋升开发效率的同时,减少了代码的可读性。

当然该计划会对业务代码有肯定的侵入性,不过能够通过注解的模式,最大限度的升高这种侵入性。

具体实操

上面就计划三,进行具体的代码演示。

首先在网关侧,须要对进来的申请header增加外网标识符: from=public

@Componentpublic class AuthFilter implements GlobalFilter, Ordered {    @Override    public Mono < Void > 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注解即可

@GetMapping ( "/role/add" )@OnlyIntranetAccesspublic String onlyIntranetAccess() {    return "该接口只容许外部服务调用";}

你学会了吗?

版权申明:本文为CSDN博主「肥肥技术宅」的原创文章,遵循CC 4.0 BY-SA版权协定,转载请附上原文出处链接及本申明。原文链接:https://blog.csdn.net/m0_71777195/article/details/127243452

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!