1 缘起

继gateway限流篇:https://blog.csdn.net/Xin_101/article/details/127890605
之后,继续补充网关统一鉴权的相关应用,
网关作为所有流量入口,承接所有请求,因此,可以在网关层统一做鉴权,
授权的放行,未授权的禁行,这里,可以添加黑白名单的功能,
白名单,无需鉴权,直接放行;
黑名单,直接禁行,
本文,即通过实战讲解网关鉴权以及黑白名单的使用。

2 架构

整体架构如下图所示,
由图可知,该体系共有三部分:
(1)网关层:做统一鉴权,保护后面的服务;
(2)注册中心层:管理所有服务;
(3)服务层:业务或其他功能性服务。

3 网关配置

网关配置的白名单是针对保护的资源,
当用户访问白名单的资源时,无需鉴权,即直接通过约定,即可获取正确的响应,
访问非白名单的资源时,需要鉴权成功后,才能获取正确的响应,否则,无法获取正确的响应。

3.1 白名单配置

白名单配置有两种方式,
(1)在启动的文件application.yml中配置;
(2)在数据库Redis或MySQL中配置,启动应用时,需要将数据加载到内存(JVM),
如何在SpringBoot启动时加载外部数据到内存参见:https://blog.csdn.net/Xin_101/article/details/127945236;
简单起见,本文直接在配置文件application.yml中配置白名单,
样例如下:

request:white-list:- /api/v1/get/test

3.2 白名单映射的实体

由上面的配置可知,映射的实体中数据类型为List,
白名单实体如下图所示,完整样例在图后面。

package com.monkey.gateway_template.config;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.List;/*** 请求白名单.** @author xindaqi* @since 2022-11-19 15:23*/
@Component
@ConfigurationProperties("request")
public class RequestWhiteList {/*** 白名单列表*/List<String> whiteList;public List<String> getWhiteList() {return whiteList;}public void setWhiteList(List<String> whiteList) {this.whiteList = whiteList;}
}

3.2 请求链配置

为了使网关具有统一鉴权的功能,就需要在网关服务中添加请求拦截功能,通过实现GlobalFilter接口来拦截请求。
测试样例核心如下图所示,核心部分均有注释,源码在图后面。
这里为了方便测试,在非白名单鉴权时,没有做token校验,只判断是否在请求头中携带token,
实际应用中开发者自定这部分认证逻辑,比如通过Redis、JWT、Oauth2.0等。

package com.monkey.gateway_template.config;import com.google.gson.Gson;
import com.monkey.gateway_template.response.Response;
import org.apache.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import javax.ws.rs.core.MediaType;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;/*** 请求拦截器(过滤器).** @author xindaqi* @since 2022-11-19 15:18*/
@Component
public class RequestFilter implements GlobalFilter, Ordered {private static final Logger logger = LoggerFactory.getLogger(RequestFilter.class);private static final String TOKEN = "token";// 获取配置的白名单@ResourceRequestWhiteList requestWhiteList;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取请求的URI,网关配置uri的lb时做了剪裁,所以,直接使用原生接口的URI,无需拼接其他内容String requestPath = exchange.getRequest().getPath().value();// 白名单接口直接放行if (Objects.nonNull(requestWhiteList) && requestWhiteList.getWhiteList().contains(requestPath)) {return chain.filter(exchange);}// 非白名单接口需要鉴权:请求头携带tokenList<String> tokenList = exchange.getRequest().getHeaders().get(TOKEN);// 这里为了方便测试,没有做token校验,只判断是否在请求头中携带token,// 实际应用中开发这自定这部分认证逻辑if (Objects.isNull(tokenList) || tokenList.size() == 0) {Gson gson = new Gson();// 这里开发者可以自定义响应的内容,我自己构建的对象Responsebyte[] data = gson.toJson(Response.invalidToken()).getBytes(StandardCharsets.UTF_8);ServerHttpResponse response = exchange.getResponse();DataBuffer buffer = response.bufferFactory().wrap(data);// 状态码配置:未授权401response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);return response.writeWith(Mono.just(buffer));}return chain.filter(exchange);}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}

4 测试

准备的测试接口如下:
接口由其他服务提供,测试使用的为自建的producer服务,原生接口URI如下表所示

序号 状态 接口
1 白名单接口 /api/v1/get/test
2 非白名单接口 /api/v1/biz/test

producer是通过网关进行访问的,网关和producer均注册到同一个注册中心集群,
所以无需关注producer的IP和PORT,通过网关已经配置,参见gateway限流篇:https://blog.csdn.net/Xin_101/article/details/127890605
所以请求时,通过网关的IP和PORT以及配置的断言Path,这里配置的为producer-server,
所以通过网关请求produer接口时需要添加produer-server前缀。
为了使限流生效,断言Path切不可与服务名相同。

4.1 白名单

白名单接口无需进行授权,直接访问,按照约定数据即可获取正确的数据。
测试结果如下图所示。

4.2 非白名单

非白名单接口需要进行鉴权,
授权通过后,方可获取正确的结果,如果授权失败,则返回未授权相关信息,
测试结果如下图所示。

5 小结

  • 白名单配置有两种方式,
    (1)在启动的文件application.yml中配置;
    (2)在数据库Redis或MySQL中配置,启动应用时,需要将数据加载到内存(JVM),
    如何在SpringBoot启动时加载外部数据到内存参见:https://blog.csdn.net/Xin_101/article/details/127945236;
  • 网关拦截请求核心是实现GlobalFilter接口,重写方法filter(ServerWebExchange exchange, GatewayFilterChain chain)。

实战讲解网关接口统一认证SpringCloudGateway(图+文)相关推荐

  1. 实战讲解Spring定时任务:@Scheduled(图+文+源码)

    1 缘起 最近看到有些定时任务的项目, 使用了Spring自带的定时任务系统,通过添加@Scheduled注解的方式实现, 并且,使用了不只cron表达式的方式实现定时执行, 恍然大悟,原来@Sche ...

  2. 14-网关实战:网关层整合 Swagger 聚合API文档

    上节课介绍了网关层的认证鉴权,今天这节介绍一下网关层如何聚合API接口文文档. 为什么需要聚合API接口文档? 大型微服务系统模块众多,木谷博客系统就有9个,如果这些服务的接口地址没有一个统一,那么客 ...

  3. 实践讲解Spring配置中心config(图+文,本地文件方式)

    1 缘起 微服务的学习过程中,发现了许多服务的配置是相同的,并且项目稳定运行期间不会轻易变更, 于是,自己开始做实验,将这些相同的配置提取出来放在配置中心, 各个服务需要时,通过这个配置中心获取,Sp ...

  4. 实践讲解死锁及死锁检测(图+文+代码)

    1 缘起 在学习ArrayBlockingQueue(ABQ)的过程中, 实现队列阻塞相关的功能是通过java.util.concurrent.locks.Condition, 如enqueue的no ...

  5. 【.NET Core项目实战-统一认证平台】第三章 网关篇-数据库存储配置(1)

    [.NET Core项目实战-统一认证平台]第三章 网关篇-数据库存储配置(1) 原文:[.NET Core项目实战-统一认证平台]第三章 网关篇-数据库存储配置(1) [.NET Core项目实战- ...

  6. 【.NET Core项目实战-统一认证平台】第四章 网关篇-数据库存储配置(2)

    [.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) 原文:[.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) [.NET Core项目实战- ...

  7. 【.NET Core项目实战-统一认证平台】第七章 网关篇-自定义客户端限流

    上篇文章我介绍了如何在网关上增加自定义客户端授权功能,从设计到编码实现,一步一步详细讲解,相信大家也掌握了自定义中间件的开发技巧了,本篇我们将介绍如何实现自定义客户端的限流功能,来进一步完善网关的基础 ...

  8. 【.NET Core项目实战-统一认证平台】第六章 网关篇-自定义客户端授权

    上篇文章[.NET Core项目实战-统一认证平台]第五章 网关篇-自定义缓存Redis 我们介绍了网关使用Redis进行缓存,并介绍了如何进行缓存实现,缓存信息清理接口的使用.本篇我们将介绍如何实现 ...

  9. 【.NET Core项目实战-统一认证平台】第五章 网关篇-自定义缓存Redis

    上篇文章[.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2)我们介绍了2种网关配置信息更新的方法和扩展Mysql存储,本篇我们将介绍如何使用Redis来实现网关的所有缓存功 ...

  10. 【.NET Core项目实战-统一认证平台】第十二章 授权篇-深入理解JWT生成及验证流程...

    上篇文章介绍了基于Ids4密码授权模式,从使用场景.原理分析.自定义帐户体系集成完整的介绍了密码授权模式的内容,并最后给出了三个思考问题,本篇就针对第一个思考问题详细的讲解下Ids4是如何生成acce ...

最新文章

  1. java user.dir 设置_使用java系统属性user.dir读取配置文件
  2. pip install 另一个程序正在使用此文件,进程无法访问
  3. 先贴上代码:Random快排,快排的非递归实现
  4. 新学语言python和JS
  5. delphi中处理数据类型错误的方法
  6. box-sizing详解
  7. [html] 你知道什么是反向链接吗?它有什么应用场景呢?
  8. 如何利用openssl来计算md4, md5, sha1, sha256, sha384, sha512等常用哈希值?
  9. Mysql插入中文时错误:ERROR 1366 (HY000): Incorrect string value: '\xE6\x9D\x8E\xE5\x8B\x87' for column
  10. php读取excel 报错_php读取excel文件 更新修改excel
  11. MDK5与Keil C51安装、合并、pack支持包的安装、STC芯片选型头文件的添加、界面美化(保姆级教程)
  12. 老鱼Python数据分析——篇十五:“选股宝”使用API下载JSON格式数据
  13. 键盘常用键的asii值
  14. 微信小程序实现手机屏幕左右旋转,页面元素左右移动,小程序加速计
  15. java http请求发送unicode_c++ 使用httpclient获取网页及utf8与unicode之间转码
  16. NUC系列迷你电脑改装苹果网卡的又一神器方案
  17. powerquery分组,PowerQuery:如何连接分组值?
  18. 大数据学习——常用的数据分析法和模型
  19. 论文分享-《基于数据驱动多输出 ARMAX 建模的高炉十字测温中心温度》
  20. 基于Java毕业设计银行招聘系统设计源码+系统+mysql+lw文档+部署软件

热门文章

  1. linux中prometheus的使用
  2. 如何利用CustomFont+PS制作字体
  3. 搜狐新闻数据400w+
  4. java过滤器的作用_javaweb过滤器的作用,过滤器filter的作用是什么?
  5. 查看CPU最大支持内存容量
  6. rtmp协议发送mp3和aac裸流的方法
  7. Linux下安装SVN服务(CentOS7下)单仓库版(老威改良版)
  8. 程序员常用的网站(个人笔记)
  9. VMware安装Linux教程
  10. 遗传算法(四)——交叉、变异与替换