设计模式-过滤器模式(使用案例)

        过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。

        业务场景:每次请求通过网关,需要验证请求头是否携带 token,sign签名等

        类图:

AuthService:所有滤器类都必须实现的接口

AuthTokenServiceImpl:Token验证过滤器

AuthSignServiceImpl:签名验证过滤器

AuthFactory:过滤器工厂,利用SpringBoot功能特性,实现自动获取过滤器

AuthDTO:过滤器所需要的参数

AuthGatewayFilterFactory:权限校验过滤器(gateway)

AuthService:

/**
 * @Author: wmh
 * @Description: 权限校验过滤器
 * @Date: 2023/8/3 18:19
 * @Version: 1.0
 */
public interface AuthService {

	/**
	 * @Description: 过滤方法
	 * @Param authDTO: 网关上下文
	 * @return: String
	 * @Author: wmh
	 * @Date: 2023/8/3 18:12
	 */
	String apply(AuthDTO authDTO);

}

返回值可以定义为统一返回值(R)等,为了演示方便,就返回字符串了

AuthTokenServiceImpl:

import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

/**
 * @Author: wmh
 * @Description: token校验
 * @Date: 2023/8/3 18:21
 * @Version: 1.0
 */
@Slf4j
@Order(0)
@Service
public class AuthTokenServiceImpl implements AuthService {

	/**
	 * @Description: 验证token
	 * @Param authDTO: 网关上下文
	 * @return: com.norinaviation.atm.common.base.data.R
	 * @Author: wmh
	 * @Date: 2023/8/3 19:31
	 */
	@Override
	@SneakyThrows
	public String apply(AuthDTO authDTO) {
		String tokenHeader = authDTO.getHeaders().getFirst(CommonConstant.X_TOKEN);
		if (StrUtil.isBlank(appId)) {
			return "appId不能为空";
		}
		if (StrUtil.isBlank(tokenHeader)) {
			return "TOKEN不能为空";
		}
		JWT jwt = JWTUtil.parseToken(tokenHeader);
		boolean verifyKey = jwt.setKey(CommonConstant.JWT_TOKEN.getBytes()).verify();
		// 验证token是否正确
		if (!verifyKey) {
			log.info("appId:{}, TOKEN auth fail, TOKEN:{}", appId, tokenHeader);
			return "TOKEN认证失败";
		}
		boolean verifyTime = jwt.validate(0);
		// 验证token是否过期
		if (!verifyTime) {
			log.info("appId:{}, TOKEN expired, TOKEN:{}", appId, tokenHeader);
			return "TOKEN已过期";
		}
		return "success";
	}

}

AuthSignServiceImpl:

import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
 * @Author: wmh
 * @Description: 验签校验
 * @Date: 2023/8/3 18:24
 * @Version: 1.0
 */
@Slf4j
@Order(1)
@Service
public class AuthSignServiceImpl implements AuthService {

	/**
	 * @Description: 验证签名
	 * @Param authDTO: 网关上下文
	 * @return: Stirng
	 * @Author: wmh
	 * @Date: 2023/8/3 19:30
	 */
	@Override
	@SneakyThrows
	public Stirng apply(AuthDTO authDTO) {
		// 签名逻辑,业务代码就不公开了
		return "success";
	}

}

AuthFactory:

import cn.hutool.core.util.ObjectUtil;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @Author: wmh
 * @Description: 权限工厂
 * @Date: 2023/8/7 15:54
 * @Version: 1.0
 */
@Component
public class AuthFactory implements ApplicationContextAware {

	/**
	 * 过滤方式
	 */
	private List<AuthService> authFilters = new ArrayList<>();

	/**
	 * 获取应用上下文并获取相应的接口实现类
	 * @param applicationContext
	 * @throws BeansException
	 */
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// 获取实现类
		Map<Integer, AuthService> authServiceMap = new HashMap<>();
		applicationContext.getBeansOfType(AuthService.class).values().stream().forEach(authService -> {
			if (ObjectUtil.isNull(authService.getClass().getAnnotation(Order.class))) {
				authServiceMap.put(CommonConstant.DEFAULT_ORDER, authService);
			}
			else {
				authServiceMap.put(authService.getClass().getAnnotation(Order.class).value(), authService);
			}
		});
		// 根据order排序
		authServiceMap.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey())).forEach(map -> {
			authFilters.add(map.getValue());
		});
	}

	/**
	 * @Description: 是否全部符合过滤条件
	 * @Param authDTO: 网关上下文
	 * @return: String
	 * @Author: wmh
	 * @Date: 2023/8/3 19:27
	 */
	public String apply(AuthDTO authDTO) {
		for (AuthService filter : authFilters) {
			String str = filter.apply(authDTO);
			if (!StrUtil.equals(str, "success")) {
				return str;
			}
		}
		return "success";
	}

}

AuthDTO:

import lombok.Data;
import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

/**
 * @Author: wmh
 * @Description: 网关上下文
 * @Date: 2023/8/3 19:09
 * @Version: 1.0
 */
@Data
public class AuthDTO {

	/**
	 * cache headers
	 */
	private HttpHeaders headers;

	/**
	 * cache json body
	 */
	private String cacheBody;

	/**
	 * cache formdata
	 */
	private MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();

}

此类为gateway网关需要,只展示使用过滤链的代码块

AuthGatewayFilterFactory:

/**
 * @Author: wmh
 * @Description: 权限校验过滤器
 * @Date: 2023/8/3 19:15
 * @Version: 1.0
 */
@Slf4j
@Component
public class AuthGatewayFilterFactory extends AbstractGatewayFilterFactory {

	@Autowired
	private AuthFactory authFactory;

	@Override
	public GatewayFilter apply(Config config) {
		return (exchange, chain) -> {
			ServerHttpRequest serverHttpRequest = exchange.getRequest();
			...
				// 获取request body
				GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.CACHE_GATEWAY_CONTEXT);
				AuthDTO authDTO = new AuthDTO();
				authDTO.setHeaders(gatewayContext.getHeaders());
				authDTO.setCacheBody(gatewayContext.getCacheBody());
				authDTO.setFormData(gatewayContext.getFormData());
				// 验证
				String strr = authFactory.apply(authDTO);
			...
			return chain.filter(exchange);
		};
	}

}

Gateway相关:SpringCloud-Gateway实现网关_springcloud配置网关_W_Meng_H的博客-CSDN博客网关作为流量的入口,常用的功能包括路由转发、权限校验、限流等Spring Cloud 是Spring官方推出的第二代网关框架,由WebFlux+Netty+Reactor实现的响应式的API网关,它不能在传统的servlet容器工作,也不能构建war包。基于Filter的方式提供网关的基本功能,例如说安全认证、监控、限流等。_springcloud配置网关https://blog.csdn.net/W_Meng_H/article/details/129775851

CommonConstant(常量类):

/**
 * @Author: wmh
 * @Description: 常用变量
 * @Date: 2023/3/30 10:29
 * @Version: 1.0
 */
@Component
public class CommonConstant {

	// JWT密钥
	public static String JWT_TOKEN;

	// 请求头中的token
	public static final String X_TOKEN = "X-TOKEN";

	// 请求头中的签名
	public static final String X_SIGN = "X-SIGN";

	// 请求头中的appId
	public static final String X_APPID = "X-APPID";

	// 请求头中的时间戳
	public static final String X_TIMESTAMP = "X-TIMESTAMP";

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/80856.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML和JavaScript实现一个简单的计算器

使用HTML和JavaScript实现一个简单的计算器。 一、绘制键盘 <!DOCTYPE html> <html> <head><title>Simple Calculator</title><style>.calculator {display: grid;grid-template-columns: repeat(4, 1fr);grid-gap: 5px;padding: 10px;}.…

Stable Diffusion 告别复制关键词,高质量提示词自动生成插件

在使用SD时,我们经常会遇到心中无想法,或不知如何描述心中所想的图像。有时由于提示词的选择不当,生成的图片质量也不尽如人意。为此,我今天为大家推荐一个高质量的提示词自动生成插件——One Button Prompt。 下面是他生成的一些样图。 文章目录 插件安装插件说明主菜单工…

【ES6】箭头函数和普通函数的区别

它们之间的区别&#xff1a; &#xff08;1&#xff09;箭头函数没有自己的this。 &#xff08;2&#xff09;不可以当作构造函数&#xff0c;不可以对箭头函数使用new命令&#xff0c;否则抛出错误。 &#xff08;3&#xff09;不可以使用arguments对象&#xff0c;该对象在函…

ABeam×Startup丨德硕管理咨询(深圳)创新研究团队前往灵境至维·既明科技进行拜访交流

近日&#xff0c;德硕管理咨询&#xff08;深圳&#xff09;&#xff08;以下简称“ABeam-SZ”&#xff09;创新研究团队一行前往灵境至维既明科技有限公司&#xff08;以下简称“灵境至维”&#xff09;进行拜访交流&#xff0c;探讨线上虚拟空间的商业模式。 现场合影 &…

VR/AR眼镜方案,MTK联发科平台智能眼镜安卓主板设计方案

随着人工智能在不同领域的逐渐深入&#xff0c;人们对一款产品的需求不再局限于某种单一的功能或单一场景&#xff0c;尤其是在工业医疗等专业领域&#xff0c;加快数字化转型才能实现产业的升级。 AR智能眼镜&#xff0c;是一个可以让现场作业更智能的综合管控设备。采用移动…

华为OD机试 - 秘钥格式化 - 双指针(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

Java创建对象的几种方式

在Java中&#xff0c;对象是程序中的一种基本元素&#xff0c;它通过类定义和创建。本篇教程旨在介绍Java中创建对象的几种方式&#xff0c;包括使用new关键字、反射、clone、反序列化等方式。 使用new关键字创建对象 在Java中&#xff0c;最常用的创建对象方式是使用new关键…

ES踩坑记录之UNASSIGNED分片无法恢复

问题背景 换节点 我们线上有一套ES集群&#xff0c;三台机器&#xff0c;共运行了6个节点。一直在线上跑了几个月也一直没出什么问题。然而好巧不巧&#xff0c;就在昨天&#xff0c;集群中的3号节点磁盘出现故障&#xff0c;导致机器直接瘫痪。本来大家觉得问题不大&#xf…

LeetCode128.最长连续序列

我这个方法有点投机取巧了&#xff0c;题目说时间复杂度最多O(n),而我调用了Arrays.sort(&#xff09;方法&#xff0c;他的时间复杂度是n*log(n)&#xff0c;但是AC了&#xff0c;这样的话这道题还是非常简单的&#xff0c;创建一个Hashmap&#xff0c;以nums数组的元素作为ke…

【C++初阶】引用计数和写时拷贝是什么?用来干嘛的?

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

08-微信小程序视图层

08-微信小程序视图层 文章目录 视图层 ViewWXML数据绑定列表渲染条件渲染模板引用importimport 的作用域include WXSS尺寸单位样式导入内联样式选择器全局样式与局部样式 WXS注意事项页面渲染数据处理 视图层 View 框架的视图层由 WXML 与 WXSS 编写&#xff0c;由组件来进行…

从零玩转系列之微信支付实战PC端装修我的订单页面 | 技术创作特训营第一期

一、前言 欢迎来到本期的博客&#xff01;本篇文章是 PC 端的结尾了,前面经历过九个章节到本章节刚刚好十章节感谢观看我的文章,那么接下来我们将要编写的是我的订单页面. GGBOM! 本篇完毕后将是 UniApp 的篇章感受移动端的诱惑 &#x1f497; 本次为前端知识点如果不懂前段可以…

人流目标跟踪pyqt界面_v5_deepsort

直接上效果图 代码仓库和视频演示b站视频006期&#xff1a; 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 代码展示&#xff1a; YOLOv5 DeepSORT介绍 YOLOv5 DeepSORT是一个结合了YOLOv5和DeepSORT算法的目标检测与多目标跟踪系统。让我为您详细解释一…

RocketMQ消费者可以手动消费但无法主动消费问题,或生成者发送超时

1.大多数是配置问题 修改rocketmq文件夹broker.conf 2.配置与集群IP或本地IPV4一样 重启 在RocketMQ独享实例中支持IPv4和IPv6双栈&#xff0c;主要是通过在网络层面上同时支持IPv4和IPv6协议栈来实现的。RocketMQ的Broker端、Namesrv端和客户端都需要支持IPv4和IPv6协议&…

SAP安全库存-安全库存共享、安全库存简介

SAP系统中的安全库存用于管理计划外和计划内的库存需求,在某些行业中,由于不同的情况,如意外损耗、损坏、环境问题、制造工艺问题、需求增加等,通常会出现意外的库存需求。 SAP提供了维护安全库存的处理方式来处理这样的问题,安全库存的字段信息在主数据视图中,在物料需…

CentOS系统环境搭建(九)——centos系统下使用docker部署项目

centos系统环境搭建专栏&#x1f517;点击跳转 关于Docker-compose安装请看CentOS系统环境搭建&#xff08;三&#xff09;——Centos7安装Docker&Docker Compose&#xff0c;该文章同样收录于centos系统环境搭建专栏。 Centos7部署项目 采用前后端分离的形式部署。使用Do…

三维可视化平台有哪些?Sovit3D可视化平台怎么样?

随着社会经济的发展和数字技术的进步&#xff0c;互联网行业发展迅速。为了适应新时代社会发展的需要&#xff0c;大数据在这个社会经济发展过程中随着技术的进步而显得尤为重要。同时&#xff0c;大数据技术的快速发展进程也推动了可视化技术的飞速发展&#xff0c;国内外各类…

融媒行业落地客户旅程编排,详解数字化用户运营实战

移动互联网时代是流量红利的时代&#xff0c;企业常用低成本的方式进行获客&#xff0c;“增长黑客”的概念大范围传播。与此同时&#xff0c;机构媒体受到传播环境的影响&#xff0c;也开始启动全行业的媒体融合转型。在此背景下&#xff0c;2015 年神策数据成立&#xff0c;核…

八、Linux下,grep/wc/管道符/echo/重定向符/tail如何使用?

1、grep命令 &#xff08;1&#xff09;主要用于文件 &#xff08;2&#xff09;主要作用是“通过关键字&#xff0c;过滤文件行” &#xff08;3&#xff09;示例&#xff1a; 2、wc命令 &#xff08;1&#xff09;统计文件的行数、单词数等 &#xff08;2&#xff09;示例…
最新文章