责任链设计模式的一次实践

news/2024/4/28 14:16:44/文章来源:https://blog.csdn.net/weixin_42195284/article/details/129706988

业务需求

框架:SSH

需要对全部接口的响应体 ResponseBody 做 XSS 拦截

解决方案

在全局拦截器中检测 Response Body 是否有非法字符,如果有,就抛出异常。

实际上,在 struts2 的拦截器上,我发现

即使修改了 action 中的返回结果,即使直接使用 HttpServletResponse 的 write 打印错误信息。

这些修改都不会成功,因为请求早已提交,所以当发现 Response Body 出现非法字符时,因为无法修改 响应内容,非法字符被直接返回给了用户。

此时,点进 struts2 源码中查看,发现可以抛出异常,这样也算一种解决方法:修改了响应体。

因为在这个拦截器中拿到了 action 对象,则需要判断其中的返回值字段是否合法,而这个项目中返回值字段存在以下这么多种。。。

 

也就是说,每个对象使用的返回值字段都不一样。

现在要判断的是 一个对象中的 这些字段 中有没有 非法字符。

以下是我第一版写的判断代码

 当时我以为要判断的字段就 2-3 个,所以直接 if 嵌套了,可是当我重新梳理后,居然有 24 个字段。

重写刻不容缓。

 

使用责任链模式解决问题

责任节点定义

public interface XssHandler {/*** xss 拦截* @param action 要拦截的 action 对象*/boolean xss(Object action);/*** 责任链:设置下一个责任节点** @param fieldName 下一个责任节点要拦截的字段* @param xssHandlerType 下一个责任节点要拦截的字段类型*/XssHandler nextHandler(String fieldName, XssHandlerType xssHandlerType);/*** 为当前责任节点设置要拦截的字段名*/void setFieldName(String fieldName);}

具体实现一

public class StringXssHandler extends BaseXssHandlerTemplate<String> {@Overridepublic boolean handlerXss(String checkObject) {boolean result = XssUtils.stripXSS(checkObject);if (result) {return false;}return true;}
}

具体实现二

public class ListXssHandler extends BaseXssHandlerTemplate<List> {@Overridepublic boolean handlerXss(List checkObject) {for (Object re : checkObject) {Field[] declaredFields = re.getClass().getDeclaredFields();for (Field declaredField : declaredFields) {if (declaredField.getType() == String.class) {// 校验 StringdeclaredField.setAccessible(true);String value;try {value = (String) declaredField.get(re);} catch (IllegalAccessException e) {return true;}if (XssUtils.stripXSS(value)) {// xss 了,此次请求不合法return false;}}}}return true;}}

具体实现三

public class MapXssHandler extends BaseXssHandlerTemplate<Map> {@Overridepublic boolean handlerXss(Map checkObject) {// 遍历 mapSet keySet = checkObject.keySet();for (Object key : keySet) {Object value = checkObject.get(key);if (value instanceof String) {// 如果 map 里的值是 String,则进行 xss 校验String mapStringValue = (String) value;if (XssUtils.stripXSS(mapStringValue)) {// xss 了,此次请求不合法return false;}}}return true;}}

类图

 其中混合了一个模板模式 

BaseXssHandlerTemplate

这个类我是想把一切操作都准备好,最终留给子类做的就是单纯的针对一个对象进行检查。

/*** 模板模式,最基本的实现,实现基本操作,真实的 xss 校验留给子类实现* <CheckObjectType> 要检查的字段类型** @author SUN* @date 2023/3/22*/
public abstract class BaseXssHandlerTemplate<CheckObjectType> implements XssHandler {/*** 下一个责任节点*/private XssHandler nextHandler;/*** 当前责任节点要校验的字段名*/private String fieldName;/*** 直接获取到要处理的字段,字段有值就传给子类做真实的 xss 校验** @param action 要拦截的 action 对象*/@Overridepublic final boolean xss(Object action) {Class<?> actionClass = action.getClass();Field field;try {field = actionClass.getDeclaredField(getFieldName());} catch (NoSuchFieldException e) {// 没有这个字段,传给后面执行return goon(action);}field.setAccessible(true);try {Object checkObject = field.get(action);if (checkObject == null) {// 没有这个字段,传给后面执行return goon(action);}// 让子类实现真实的 检查方法CheckObjectType checkObjectType = (CheckObjectType) checkObject;boolean result = handlerXss(checkObjectType);if (result) {return goon(action);} else {return false;}} catch (IllegalAccessException e) {e.printStackTrace();// 不会出现这个问题因为已经 field.setAccessible(true);}// 直接成功return true;}/*** 子类负责处理 xss 拦截*/public abstract boolean handlerXss(CheckObjectType checkObject);public boolean goon(Object action) {if (nextHandler == null) {return true;}return nextHandler.xss(action);}/// ==================================  setter / getter ===================================@Overridepublic final XssHandler nextHandler(String fieldName, XssHandlerType xssHandlerType) {XssHandler xssHandler = XssHandlerFactory.newHandler(fieldName, xssHandlerType);this.nextHandler = xssHandler;return xssHandler;}@Overridepublic final void setFieldName(String fieldName) {this.fieldName = fieldName;}public final String getFieldName() {return fieldName;}public final XssHandler getNextHandler() {return nextHandler;}}

子类实现

新建一个处理器责任节点只需要完成以下代码。

 

责任节点定义完了,看看代码如何组织

public class XssActionInterceptor {private final static XssHandler XSS_HANDLER;static {XSS_HANDLER =XssHandlerFactory.newHandler("result", STRING);XSS_HANDLER.nextHandler("map", MAP).nextHandler("errorCode", STRING).nextHandler("propertyVO", OBJECT).nextHandler("resContainer", RES_CONTAINER).nextHandler("payedDataList", STRING).nextHandler("ownerInformation", OBJECT).nextHandler("jsonData", LIST).nextHandler("feeDataList", STRING).nextHandler("collectInfo", STRING).nextHandler("payableDataList", STRING).nextHandler("roomInfo", STRING).nextHandler("dataList", LIST).nextHandler("propertys", STRING).nextHandler("results", STRING).nextHandler("logList", STRING).nextHandler("feeDetails", STRING).nextHandler("judgeNo", STRING).nextHandler("roomLogList", STRING).nextHandler("roomFees", STRING).nextHandler("payDetails", STRING).nextHandler("resultContainer", RESULT_CONTAINER).nextHandler("resultCode", STRING).nextHandler("exeResult", STRING);}}

 

使用枚举定义了类型 于 处理器之间的映射

然后使用工厂模式直接根据枚举类创建 对应的 处理器责任节点

 

忘记说了一点,就是责任的流转,责任链要往后传递

BaseXssHandlerTemplate

最后看看使用

 

 今日水了一篇文章

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

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

相关文章

yum安装docker以及安装指定版本docker

Docker是Docker.Inc公司开源的一个基于轻量级虚拟化技术的容器引擎项目,整个项目基于Go语言开发&#xff0c;并遵从Apache 2.0协议。通过分层镜像标准化和内核虚拟化技术&#xff0c;Docker使得应用开发者和运维工程师可以以统一的方式跨平台发布应用&#xff0c;并且以几乎没有…

在Java中,使用HttpUtils实现发送HTTP请求

HTTP请求&#xff0c;在日常开发中&#xff0c;还是比较常见的&#xff0c;今天给大家分享HttpUtils如何使用。 阅读本文&#xff0c;你将收获&#xff1a; 简单总结HTTP请求常用配置&#xff1b;JavaLib中HttpUtils如何使用&#xff1b;如何封装HTTP请求工具类。 第一部分&a…

【Unity入门】3D物体

【Unity入门】3D物体 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity入门系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;物体移动旋转缩放 &#xff08;1&#xff09;物体移动 在上一篇文章【Unity入门】场景视图操作我们学会了在场景中创建3…

开源供应链管理系统 S2B2B2C系统方案及源码输出

连锁供应链的管理&#xff0c;包括供应链的仓库管理、业务员管理、门店订货管理、门店管理、门店前端拓客管理&#xff0c;相关的功能结构图如下&#xff1a; 整个方案含PC、小程序端&#xff0c;源码&#xff01; 功能列表&#xff1a; 仓库管理&#xff1a;包括仓库布局、库存…

Fabric系列 - TLS身份验证

排序节点&#xff08;Orderer&#xff09;要启用TLS身份验证 对等节点&#xff08;Peer&#xff09;要启用TLS的身份验证 Gossip 消息传递 gossip 层使用 TLS 绑定来验证连接另一端的对等方的身份。 通过 Peer 节点 TLS 层来处理点对点消息的安全性&#xff0c;不需要使用签名…

OpenAI创始人:GPT-4的研究起源和构建心法

OneFlow编译 翻译&#xff5c;杨婷、贾川、徐佳渝 三十年前&#xff0c;互联网&#xff08;Web 1.0&#xff09;时代开启。人们只能在笨重的电脑上用鼠标点击由HTML编写的网页文本&#xff0c;随后开始支持插入图片&#xff0c;可以上传视频&#xff0c;于是有了网络新闻、搜索…

一次小破站JS代码审计出XSS漏洞思路学习

今天看了小破站一个大佬的分析&#xff0c;感觉思路很有意思&#xff0c;感兴趣的xdm可以到大佬视频下提供的链接进行测试&#xff08;传送门&#xff09;这类社交平台的XSS漏洞利用起来其实危害是特别大的&#xff0c;利用XSS能在社交平台上呈现蠕虫式的扩散&#xff0c;大部分…

【人人都能读标准】10. 作用域链与闭包

本文为《人人都能读标准》—— ECMAScript篇的第10篇。我在这个仓库中系统地介绍了标准的阅读规则以及使用方式&#xff0c;并深入剖析了标准对JavaScript核心原理的描述。 在8.执行环境我们说过&#xff0c;由ECMAScript代码创建的执行上下文会有一个词法环境的组件&#xff0…

【Effective C++详细总结】第四章 设计与声明

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;C/C知识点 &#x1f4e3;专栏定位&#xff1a;整理一下 C 相关的知识点&#xff0c;供大家学习参考~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;…

Flink-转换算子

基本转换算子 map(映射) filter&#xff08;过滤&#xff09; flatMap&#xff08;扁平映射&#xff09; 聚合算子 keyBy&#xff08;按键分区&#xff09; 简单聚合 reduce&#xff08;归约聚合&#xff09; UDF介绍 函数类 富函数类 数据源读入数据之后&#xff0c;我们就可…

Neodynamic EPLPrinter SDK 2.0 for .NET Crack

Neodynamic EPLPrinter Emulator SDK for .NET Standard V2.0 添加对 FK&#xff08;删除表单&#xff09;、FR&#xff08;检索表单&#xff09;和 FS&#xff08;存储表单&#xff09;表单相关命令的支持。 21月 2023&#xff0c; 10 - 34&#xff1a;<>新版本 特征…

如何在24小时内让你的网站跻身谷歌前列?

在当今互联网时代&#xff0c;拥有一个排名靠前的网站对于企业来说非常重要&#xff0c;因为这意味着更多的流量和更高的曝光率。 而谷歌&#xff08;Google&#xff09;是全球最受欢迎的搜索引擎之一&#xff0c;因此在谷歌的搜索结果中排名靠前非常重要。 那么如何在24小时…

tomcat服务器前端部署【Tomcat Manager、思路分析】

问题描述 当前需要我进行前端代码的部署&#xff0c;但是我忘记了这个系统对应的部署位置&#xff0c;但是隐约记得好像是通过tomcat部署的。 然后当时为了方便部署&#xff0c;我们打开了Tomcat Manager 以下是基于Tomcat Manager的&#xff0c;没有打开的需要前往tomcat下载…

详解:企业知识管理的制作步骤!

随着信息技术的快速发展&#xff0c;企业面临着海量的信息和知识&#xff0c;如何管理和利用这些信息和知识&#xff0c;已经成为企业发展的重要问题。知识管理是一种管理方法和技术&#xff0c;旨在帮助企业有效地管理和利用知识资产&#xff0c;提高企业的创新能力和竞争力。…

【CSS】浮动 ② ( 浮动语法简介 | 文字环绕效果 | 左浮动 | 右浮动 )

文章目录一、浮动语法简介1、语法说明2、没有浮动的效果3、左浮动的效果4、右浮动的效果5、右浮动 外边距效果二、完整代码示例一、浮动语法简介 1、语法说明 为 元素 设置了 浮动 CSS 属性 , 可以实现 : 元素标签 不再受 标准流 控制 ; ( 块级元素 , 行内元素 , 行内块元素 …

【嵌入式Linux学习笔记】platform设备驱动和input子系统

对于Linux这种庞大的操作系统&#xff0c;代码重用性非常重要&#xff0c;所以需要有相关的机制来提升效率&#xff0c;去除重复无意义的代码&#xff0c;尤其是对于驱动程序&#xff0c;所以就有了platform和INPUT子系统这两种工作机制。 学习视频地址&#xff1a;【正点原子…

【JavaSE】泛型中的通配符

文章目录1. 概述2. 上界通配符 < ? extends E>3. 下界通配符 < ? super E>3. &#xff1f;和 T 的区别1. 概述 Java 泛型&#xff08;generics&#xff09;是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制&#xff0c;该机制允许开发者在编译时…

【QT神奇Bug】中文乱码、括号乱码、冒号乱码【2023.03.22】

&#x1f60d;Qt乱码疑难杂症解决方案 Solved by Yang Naifen. &#x1f4fa;视频讲解地址&#xff1a;【Qt疑难杂症之乱码-哔哩哔哩】 https://b23.tv/83MmXru 附言&#xff1a;解决这个bug按照我当前的薪资&#xff0c;至少四百RMB。都是工农阶级的工友&#xff0c;有bug一…

本地调试Java程序时只对部分接口忽略代理

场景 今天有位朋友问了个问题&#xff0c;在本地IDE开发工具调试代码的时候&#xff0c;怎么不动代码的情况只针对部分API走proxy&#xff0c;因为他们的代码只需要在本地调试的时候才要用到Proxy&#xff0c;而平时都是部署在云上&#xff0c;是用不到Proxy的&#xff0c;所以…

JDBC基础,介绍了简单的连接数据库,并通过在后端写SQL语句对数据库进行基本的增删查改操作

一、JDBC基础 跟数据库连接&#xff0c;并且可以对数据库里面的数据通过SQL语句进行处理等操作。 1.1 JDBC JDBC是SUN公司的&#xff0c;所以要按照他们的规范来&#xff0c;因为MYSQL和Oracle都是SUN公司的。三个产品都是一个公司的&#xff0c;一般不会出现兼容性不好的问…