SpringCloud 实战:禁止直接访问后端服务
作者 | 单一色调 责编 | 张文
来源 | 转载自 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 实战:禁止直接访问后端服务相关推荐
- [菜鸟SpringCloud实战入门]第九章:服务网关Zuul体验
前言 欢迎来到菜鸟SpringCloud实战入门系列(SpringCloudForNoob),该系列通过层层递进的实战视角,来一步步学习和理解SpringCloud. 本系列适合有一定Java以及Sp ...
- 访问后端服务 报错504 问题记录
** 1.问题现象 ** 服务运行在集群中,早上起来客户反应登录没有反应,调用接口报错504 2.解决步骤 2.1 排查服务域名解析是否出问题, nslookup 域名 内网进去其它pod进去,解析正 ...
- OpenShift 4 之Service Mesh教程(4)- 跟踪访问后端服务超时
<OpenShift 4.x HOL教程汇总> 说明:本文已经在OpenShift 4.8环境中验证 本文说明如何在Istio中的VirtualService中设置访问的timeout特性 ...
- 微信小程序访问后端服务器
小程序前端代码如何访问后端服务? 1 访问本地tomcat服务 由于小程序不能设置localhost和ip地址格式的域名,因此这里需要勾选开发者工具中的右上角的详情下的"不校验合法域 ...
- nginx访问后端偶尔超时问题
一.问题描述 正常访问截图 通过浏览器F12明显可以看到每刷新几次访问,就有一次响应时间比较长的. 二.排错之路 首先怀疑是否是后端服务有问题,所以导致会出先这个故障,后面确认直接访问后端服务,不会出 ...
- SpringCloud实战5-Feign声明式服务调用
SpringCloud实战5-Feign声明式服务调用 在前面的文章中可以发现当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还 ...
- Java微服务——SpringCloud实战篇2:整合Gateway、Config、Bus
Java微服务--SpringCloud实战篇2:整合Gateway.Config.Bus 如果小伙伴在阅读下列内容时,对于编写SpringCloud项目是零基础,那么请先阅读小编的另一篇博文:&qu ...
- Amazon API Gateway使用IP白名单控制后端服务访问
一图胜千言 目标 我们需要在Amazon API Gateway设置资源策略,用于控制某些IP段能够访问特定后端服务. 前提 假设已经完成了Amazon API Gateway中REST API的接口 ...
- (三)SpringCloud实战微服务
一.微服务架构概述 1.1 微服务特性以及优点 每个服务可以独立运行在自己的进程里 一系列独立运行的微服务(goods,order,pay,user,search-)共同构建了整个系统 每个服务为独立 ...
最新文章
- visual studio 2005 新建C++空项目无法调试的解决方案
- linux管理员工具
- python编程难吗-都说python很简单 真的很好学么?
- 开发html5的共享单车,HTML5 SVG 共享单车(小蓝车)动画
- TCPview 介绍
- SpringCloud导学
- ios动画效果集锦(持续更新)
- shell之什么时候使用shell以及最简单的shell程序
- TZOJ 5101 A Game(区间DP)
- .NetCore中三种注入方式的思考
- mysql教程日志_MySQL日志
- 我的第二个切换图片高亮显示,给力
- 普通硬盘和固态硬盘的区别?
- [论文阅读] SASA: Semantics-Augmented Set Abstraction for Point-based 3D Object Detection
- 戴维解惑——用iTestin云测做测试怎样拿大奖
- idea配置Camunda Modeler
- CGI跟FASTCGI区别
- 视频消重伪原创版 怎么修改视频的MD5值
- 在移动互联时代下,介绍几个Android 开发的新技术
- 拒绝做焦虑贩卖者的韭菜 自主学习、焦虑、职业发展、乐观生活、资源免费分享