

Spring Cloud Alibaba 微服务实战(二十七):禁止直接访问后端服务
source link: https://mp.weixin.qq.com/s/RFBCFrm_ANf_fChYD27KIw
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用SpringCloud架构后我们希望所有的请求都需要经过网关才能访问,在不作任何处理的情况下我们是可以绕过网关直接访问后端服务的。如下,我们绕过网关直接访问后端服务也是可以获取到数据的。
那我们今天的议题就是 如何防止请求绕过网关直接访问后端服务?
解决方案
我觉得防止绕过网关直接请求后端服务的解决方案主要有三种:
-
使用Kubernetes部署
在使用Kubernetes部署SpringCloud架构时我们给网关的Service配置NodePort,其他后端服务的Service使用ClusterIp,这样在集群外就只能访问到网关了。
-
网络隔离
后端普通服务都部署在内网,通过防火墙策略限制只允许网关应用访问后端服务。
-
应用层拦截
请求后端服务时通过拦截器校验请求是否来自网关,如果不来自网关则提示不允许访问。
这里我们着重关注在应用层拦截这种解决方案。
实现思路
实现思路其实也很简单,在请求经过网关的时候给请求头中增加一个额外的Header,在后端服务中写一个拦截器,判断请求头是否与在网关设置的请求Header一致,如果不一致则不允许访问并给出提示。
当然为了防止在每个后端服务都需要编写这个拦截器,我们可以将其写在一个公共的starter中,让后端服务引用即可。而且为了灵活,可以通过配置决定是否只允许后端服务访问。
接下来我们看看核心代码。(代码中涉及 SpringBoot 编写公共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
}
以上,希望对你有所帮助!
End
干货分享
这里为大家准备了一份小小的礼物,关注公众号,输入如下代码,即可获得百度网盘地址,无套路领取!
001:《程序员必读书籍》
002:《从无到有搭建中小型互联网公司后台服务架构与运维架构》
003:《互联网企业高并发解决方案》
004:《互联网架构教学视频》
006:《SpringBoot实现点餐系统》
007:《SpringSecurity实战视频》
008:《Hadoop实战教学视频》
009:《腾讯2019Techo开发者大会PPT》
010: 微信交流群
近期热文top
我就知道你“在看”
Recommend
-
27
Nacos Discovery 是什么? 服务发现是微服务架构体系中最关键的组件之一。 如果尝试着用手动的方式来给每一个客户端来配置所有服务提供者的服务列表是一件非常困难的事,而且也不利于服务的动...
-
40
在之前的项目中我们已经实现了使用Feign调用远程接口,本章内容主要是借助sentinel实现Feign接口熔断器功能。...
-
27
今天内容主要是解决一位粉丝提的问题:如何在jwt中添加用户的额外信息并在资源服务器中获取这些数据。 涉及的知识点有以下三个...
-
7
微服务领域是不是要变天了?Spring Cloud Alibaba正式入驻Spring Cloud官方孵化器!
-
14
SpringCloud Alibaba微服务实战二十三 - Feign 性能调优 ...
-
12
SpringCloud Alibaba微服务实战二十七 使用SpringCloud架构后我们希望所有的请求...
-
6
前面文章咱们对比过网关授权与微服务授权的区别,文章也提到了,如果要实现微服务授权,一般会构建一个独立的资源服务器配置模块,否则每个后端业务都需要进行资源服务器的配置,那本节内容我们就来完成此功能。 由于间隔时间...
-
5
SpringCloud Alibaba微服务实战三十二 大家好,我是飘渺Jam,一名来自三流城市三流公司的三流程序员,这是我们的第159篇原创文章,如果你喜欢请记得给我一个点赞与转发。 这篇文章来源于粉丝...
-
18
download:Spring Cloud / Alibaba 微服务架构实战为提高搜索的精确度,推荐使用配套工具截图
-
6
SpringCloud-Alibaba致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件,方便开发者通过 Spring Cloud编程模型轻松使用这些组件来开发分布式应用服务。 依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 S...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK