作者 | 单一色调    责编 | 张文

来源 | 转载自 JAVA 日知录

前言

使用 SpringCloud 架构后,我们希望所有的请求都需要经过网关才能访问。在不作任何处理的情况下,我们是可以绕过网关直接访问后端服务的。如下,我们绕过网关直接访问后端服务也是可以获取到数据的。

那我们今天的议题就是如何防止请求绕过网关直接访问后端服务?

解决方案

我觉得防止绕过网关直接请求后端服务的解决方案主要有三种:

  • 使用 Kubernetes 部署

    在使用 Kubernetes 部署 SpringCloud 架构时,我们给网关的 Service 配置 NodePort,其他后端服务的 Service 使用 ClusterIp,这样在集群外就只能访问到网关了。

  • 网络隔离

    后端普通服务都部署在内网,通过防火墙策略限制只允许网关应用访问后端服务。

  • 应用层拦截

    请求后端服务时通过拦截器校验请求是否来自网关,如果不来自网关则提示不允许访问。

这里我们着重关注在应用层拦截这种解决方案。

实现

实现思路

实现思路其实也很简单,在请求经过网关的时候给请求头中增加一个额外的 Header,在后端服务中写一个拦截器,判断请求头是否与在网关设置的请求 Header 一致,如果不一致则不允许访问并给出提示。

当然为了防止在每个后端服务都需要编写这个拦截器,我们可以将其写在一个公共的 starter 中,让后端服务引用即可。而且为了灵活,可以通过配置决定是否只允许后端服务访问。

接下来我们看看核心代码。

实现过程

在网关 cloud-gateway 模块编写网关过滤器

@Component@Order(0)public class GatewayRequestFilter implements GlobalFilter {@Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        byte[] token = Base64Utils.encode((CloudConstant.GATEWAY_TOKEN_VALUE).getBytes());        String[] headerValues = {new String(token)};        ServerHttpRequest build = exchange.getRequest()                .mutate()                .header(CloudConstant.GATEWAY_TOKEN_HEADER, headerValues)                .build();ServerWebExchange newExchange = exchange.mutate().request(build).build();        return chain.filter(newExchange);    }
}

在请求经过网关时添加额外的 Header,为了方便这里直接设置成固定值。

建立公共 Starter 模块 cloud-component-security-starter

编写配置类,用于灵活控制服务是否允许绕过网关

@Data
@ConfigurationProperties(prefix = "javadaily.cloud")
public class CloudSecurityProperties {/*** 是否只能通过网关获取资源* 默认为True*/private Boolean onlyFetchByGateway = Boolean.TRUE;}

编写拦截器,用于校验请求是否经过网关

public class ServerProtectInterceptor implements HandlerInterceptor {private CloudSecurityProperties properties;@Override    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler){if (!properties.getOnlyFetchByGateway()) {            return true;        }String token = request.getHeader(CloudConstant.GATEWAY_TOKEN_HEADER);String gatewayToken = new String(Base64Utils.encode(CloudConstant.GATEWAY_TOKEN_VALUE.getBytes()));if (StringUtils.equals(gatewayToken, token)) {            return true;        } else {            ResultData<String> resultData = new ResultData<>();            resultData.setSuccess(false);            resultData.setStatus(HttpServletResponse.SC_FORBIDDEN);            resultData.setMessage("请通过网关访问资源");            WebUtils.writeJson(response,resultData);            return false;        }    }public void setProperties(CloudSecurityProperties properties) {        this.properties = properties;    }}

配置拦截器

public class CloudSecurityInterceptorConfigure implements WebMvcConfigurer {private CloudSecurityProperties properties;@Autowired    public void setProperties(CloudSecurityProperties properties) {        this.properties = properties;    }@Bean    public HandlerInterceptor serverProtectInterceptor() {        ServerProtectInterceptor interceptor = new ServerProtectInterceptor();        interceptor.setProperties(properties);        return interceptor;    }@Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(serverProtectInterceptor());    }}

编写 starter 装载类

@EnableConfigurationProperties(CloudSecurityProperties.class)public class CloudSecurityAutoConfigure{@Bean    public CloudSecurityInterceptorConfigure cloudSecurityInterceptorConfigure() {        return new CloudSecurityInterceptorConfigure();    }
}

建立资源文件 spring.factories,配置 Bean 的自动加载

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\   com.javadaily.component.security.configure.CloudSecurityAutoConfigure

在后端服务配置文件中添加属性配置,默认只能通过网关访问

javadaily:  cloud:    onlyFetchByGateway: true

经过以上几步,一个公共的 Starter 模块就构建完成了。

后端服务引用此公共 Starter 模块即可,以 account-service 为例

<dependency> <groupId>com.jianzh5.cloud</groupId> <artifactId>cloud-component-security-starter</artifactId></dependency>

实现效果

直接访问后端服务接口  
http://localhost:8010/account/getByCode/jianzh5

返回结果:

{  "message": "请通过网关访问资源",  "status": 403,  "success": false,  "timestamp": 1611660015830}

以上,希望对你有所帮助!

程序员如何避免陷入“内卷”、选择什么技术最有前景,中国开发者现状与技术趋势究竟是什么样?快来参与「2020 中国开发者大调查」,更有丰富奖品送不停!

☞小米澄清「手机不再支持GMS」;虾米音乐正式关停;《质量效应1》DLC 因源代码损坏而移除 | 极客头条☞一行代码没写,凭啥被尊为“第一位程序员”?
☞程序员硬核“年终大扫除”,清理了数据库 70GB 空间

SpringCloud 实战:禁止直接访问后端服务相关推荐

  1. [菜鸟SpringCloud实战入门]第九章:服务网关Zuul体验

    前言 欢迎来到菜鸟SpringCloud实战入门系列(SpringCloudForNoob),该系列通过层层递进的实战视角,来一步步学习和理解SpringCloud. 本系列适合有一定Java以及Sp ...

  2. 访问后端服务 报错504 问题记录

    ** 1.问题现象 ** 服务运行在集群中,早上起来客户反应登录没有反应,调用接口报错504 2.解决步骤 2.1 排查服务域名解析是否出问题, nslookup 域名 内网进去其它pod进去,解析正 ...

  3. OpenShift 4 之Service Mesh教程(4)- 跟踪访问后端服务超时

    <OpenShift 4.x HOL教程汇总> 说明:本文已经在OpenShift 4.8环境中验证 本文说明如何在Istio中的VirtualService中设置访问的timeout特性 ...

  4. 微信小程序访问后端服务器

    小程序前端代码如何访问后端服务? 1 访问本地tomcat服务     由于小程序不能设置localhost和ip地址格式的域名,因此这里需要勾选开发者工具中的右上角的详情下的"不校验合法域 ...

  5. nginx访问后端偶尔超时问题

    一.问题描述 正常访问截图 通过浏览器F12明显可以看到每刷新几次访问,就有一次响应时间比较长的. 二.排错之路 首先怀疑是否是后端服务有问题,所以导致会出先这个故障,后面确认直接访问后端服务,不会出 ...

  6. SpringCloud实战5-Feign声明式服务调用

    SpringCloud实战5-Feign声明式服务调用 在前面的文章中可以发现当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还 ...

  7. Java微服务——SpringCloud实战篇2:整合Gateway、Config、Bus

    Java微服务--SpringCloud实战篇2:整合Gateway.Config.Bus 如果小伙伴在阅读下列内容时,对于编写SpringCloud项目是零基础,那么请先阅读小编的另一篇博文:&qu ...

  8. Amazon API Gateway使用IP白名单控制后端服务访问

    一图胜千言 目标 我们需要在Amazon API Gateway设置资源策略,用于控制某些IP段能够访问特定后端服务. 前提 假设已经完成了Amazon API Gateway中REST API的接口 ...

  9. (三)SpringCloud实战微服务

    一.微服务架构概述 1.1 微服务特性以及优点 每个服务可以独立运行在自己的进程里 一系列独立运行的微服务(goods,order,pay,user,search-)共同构建了整个系统 每个服务为独立 ...

最新文章

  1. visual studio 2005 新建C++空项目无法调试的解决方案
  2. linux管理员工具
  3. python编程难吗-都说python很简单 真的很好学么?
  4. 开发html5的共享单车,HTML5 SVG 共享单车(小蓝车)动画
  5. TCPview 介绍
  6. SpringCloud导学
  7. ios动画效果集锦(持续更新)
  8. shell之什么时候使用shell以及最简单的shell程序
  9. TZOJ 5101 A Game(区间DP)
  10. .NetCore中三种注入方式的思考
  11. mysql教程日志_MySQL日志
  12. 我的第二个切换图片高亮显示,给力
  13. 普通硬盘和固态硬盘的区别?
  14. [论文阅读] SASA: Semantics-Augmented Set Abstraction for Point-based 3D Object Detection
  15. 戴维解惑——用iTestin云测做测试怎样拿大奖
  16. idea配置Camunda Modeler
  17. CGI跟FASTCGI区别
  18. 视频消重伪原创版 怎么修改视频的MD5值
  19. 在移动互联时代下,介绍几个Android 开发的新技术
  20. 拒绝做焦虑贩卖者的韭菜 自主学习、焦虑、职业发展、乐观生活、资源免费分享

热门文章

  1. 如何掌握眼神接触技巧?
  2. 【LeetCode 剑指offer刷题】特殊数题3:204 Count Primes
  3. 滚动效果--marquee的使用
  4. 1.jenkins持续集成-jenkins安装
  5. nginx负载均衡 加权轮询和ip_hash
  6. sql 系统 存储过程的使用方法 转载
  7. 《计算机网络》学习笔记 ·004【网络层】
  8. android 换机 iphone8,iPhone 8给了安卓用户一个换机理由
  9. 自己整理实现的python小工具
  10. pytorch项目代码总结