微服务开发时,接口不能对外暴露怎么办?

发布时间:2025-05-20 02:51:05 作者:益华网络 来源:undefined 浏览量(2) 点赞(4)
摘要:来源:码猿技术专栏 在业务开发的时候,经常会遇到某一个接口不能对外暴露,只能内网服务间调用的实际需求。面对这样的情况,我们该如何实现呢? 今天,我就来说一下码猿慢病云管理系统中是如何实现的? 码猿慢病云管理系

来源:码猿技术专栏

在业务开发的时候,经常会遇到某一个接口不能对外暴露,只能内网服务间调用的实际需求。面对这样的情况,我们该如何实现呢?

今天,我就来说一下码猿慢病云管理系统中是如何实现的?

码猿慢病云管理系统企业级医疗项目正在持续更新,需要订阅的小伙伴可以点链接联系陈某

往期文章如下:

企业级医疗项目:码猿慢病云管理系统来了!医疗系统的权限就该这样设计,稳!决定放弃 JWT 了!

常用方案

在介绍码猿慢病云管理系统中的实现方式,先来介绍常用的两种方案。

1. 网关+白名单

此方案需要在缓存中维护一套接口白名单,请求到达网关处,先判断白名单缓存中是否存在,存在则放行,反之则拦截。

该方案的好处是,对业务代码零侵入,只需要维护好白名单列表即可;

不足之处在于,白名单的维护是一个持续性投入的工作,在很多公司,业务开发无法直接触及到 redis,只能提工单申请,增加了开发成本;

另外,每次请求进来,都需要判断白名单,增加了系统响应耗时,考虑到正常情况下外部进来的请求大部分都是在白名单内的,只有极少数恶意请求才会被白名单机制所拦截,所以该方案的性价比很低。

2. 网关+AOP

相比于方案一对接口进行白名单判断而言,方案二是对请求来源进行判断,并将该判断下沉到业务侧。避免了网关侧的逻辑判断,从而提升系统响应速度。

我们可以在所有内部的调用请求头中增加一个header标志这是一个内部请求,比如加个请求头:from=Y

只要在业务接口处通过AOP的方式判断一下请求头中是否含有from=Y,如果有,则是内部请求,反之则是外部请求

实现

码猿慢病云管理系统中采用的是第二种方案:网关+AOP ,下面来介绍一下具体的代码实现。

1. 定义注解

这里AOP在码猿慢病云管理系统中采用的是注解的方式,注解如下:

@Target

({ ElementType.METHOD, ElementType.TYPE })

@Retention

(RetentionPolicy.RUNTIME)

@Documentedpublic @interface

 Inner {

 

/**

  * 是否AOP统一处理

  */
 boolean value() default true

;

}

2. 网关处理

在网关处需要对请求头中的from进行清洗,避免有意之人伪装内部请求,这里需要做的就是对每个请求直接移除from这个请求头,直接使用全局过滤器即可完成,代码如下:

/**

 * {@link

 com.code.ape.codeape.gateway.filter.CodeapeRequestGlobalFilter#filter}

 * @author

 公众号:码猿技术专栏

 * @url

 */
public class CodeapeRequestGlobalFilter implements GlobalFilterOrdered 

{

 @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) 

{

  // 1. 清洗请求头中from 参数

  ServerHttpRequest request = exchange.getRequest().mutate().headers(httpHeaders -> {

   httpHeaders.remove(SecurityConstants.FROM);

   // 设置请求时间

   httpHeaders.put(CommonConstants.REQUEST_START_TIME,

     Collections.singletonList(String.valueOf(System.currentTimeMillis())));

  }).build();

        .......

        .......

    }

3. feign接口处理

既然是内部调用,按照之前的约定是要在请求头中添加一个from=Y,因此在feign接口中需要新增这个请求头,方式很简单,比如设备feign接口,如下:

/**

 * @author

 公众号:码猿技术专栏

 * @url

 * @description

 设备的feign接口

 */
@FeignClient(contextId = "remoteDeviceService"

, value = ServiceNameConstants.DEVICE_SERVICE)

public interface RemoteDeviceService 

{

 

/**

  * 通过Sn查询

  * @param

 sn 设备SN号

  * @return

 设备详细信息

  */
 @GetMapping(value = "/device/sn/{sn}",headers = "from=Y"

)

 R<DeviceInfoVO> getBySn(@PathVariable("sn" ) String sn)

;

}

@GetMapping中的headers属性即可完成新增请求头,同样的比如@RequestMapping、@PostMapping等也是支持的。

这样的话在feign接口发出请求时则会自动在请求头中新增from=Y了。

4. AOP处理

在第1步中定义了@Inner这个注解,标注在controller方法上表示这个接口只允许内部调用,代码如下:

@IngoreAuth这个注解是绕过鉴权的作用,前面文章中也有分享。

那么这个注解内部的实现原理是什么呢?代码如下:

//com.code.ape.codeape.common.security.component.CodeapeSecurityInnerAspect@Slf

4j

@Aspect@RequiredArgsConstructorpublic class CodeapeSecurityInnerAspect implements Ordered 

{

 private final

 HttpServletRequest request;

 @SneakyThrows @Around("@within(inner) || @annotation(inner)"

)

 public Object around(ProceedingJoinPoint point, Inner inner) 

{

        //取出请求头中的from属性  String header = request.getHeader("from"

);

        //判断from===Y  if (inner.value() && !"Y"

.equals(header)) {

            //不符合规则,直接抛出异常,返回给客户端无权限   log.warn("访问接口 {} 没有权限"

, point.getSignature().getName());

   throw new AccessDeniedException("Access is denied"

);

  }

  return

 point.proceed();

 }

    .......

}

如果请求头中的from属性不匹配,则抛出AccessDeniedException异常,会被全局异常捕获,返回403的状态码,代码如下:

总结

本节内容介绍了微服务中接口不对外暴露的两种方案:

网关+白名单网关+AOP

当然还有其他的实现方式,生产中根据项目需要选择合适的方案为最佳

二维码

扫一扫,关注我们

声明:本文由【益华网络】编辑上传发布,转载此文章须经作者同意,并请附上出处【益华网络】及本页链接。如内容、图片有任何版权问题,请联系我们进行处理。

感兴趣吗?

欢迎联系我们,我们愿意为您解答任何有关网站疑难问题!

您身边的【网站建设专家】

搜索千万次不如咨询1次

主营项目:网站建设,手机网站,响应式网站,SEO优化,小程序开发,公众号系统,软件开发等

立即咨询 15368564009
在线客服
嘿,我来帮您!