SpringBoot通用的敏感词拦截
1.封装HttpServletRequestWrapper
关于为何要封装:
- 原生的HttpServletRequest对象中只能调用一次
getInputStream()
或getReader()
- 原生
getInputStram()
和getReader()
全局只能调用一次(共享这唯一的一次),他是读取请求体中的二进制网络数据,因此只能读取一次
源码解析
可以看到是读取解析request请求中的body部分的二进制流,转化为ServletInputStream类型的输入流
关于源码注释的翻译如下
封装,持久化ServletInputStream
自定义类的继承结构如下
一个通用的持久化封装类
new MyHttpServletRequestWrapper()的时候自动会将二进制流持久化到byte[]数组中,作为一个属性可以被该对象调用
/*** 继承关系:* MyHttpServletRequestWrapper——>HttpServletRequestWrapper——>HttpServletRequest* 利用Filter将原生HttpServletRequest包装为MyHttpServletRequestWrapper* (设计模式:装饰者模式)*/
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {/*** 因为一次请求的request.InputStreaam()只能调用一次。其方法获取的是网络输入流* 所以在这里定义个byte数组,来持久化该网络流*/public byte[] bytes;/*** 构造方法*/public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);//将一次性的网络IO持久化为byte数组bytes = IOUtils.toByteArray(request.getInputStream());}/*** 匿名抽象类ServletInputStream类* 需要重写InputStream中的read()方法* 需要重写ServletInputStream中的抽象方法isFinished isReady setReadListener*/@Overridepublic ServletInputStream getInputStream() throws IOException {return new ServletInputStream(){private int lastIndexRetrieved = -1;private ReadListener readListener = null;@Overridepublic boolean isFinished() {return (lastIndexRetrieved == bytes.length-1);}@Overridepublic boolean isReady() {// This implementation will never block// We also never need to call the readListener from this method, as this method will never return falsereturn isFinished();}@Overridepublic void setReadListener(ReadListener readListener) {this.readListener = readListener;if (!isFinished()) {try {readListener.onDataAvailable();} catch (IOException e) {readListener.onError(e);}} else {try {readListener.onAllDataRead();} catch (IOException e) {readListener.onError(e);}}}@Overridepublic int read() throws IOException {int i;if (!isFinished()) {i = bytes[lastIndexRetrieved+1];lastIndexRetrieved++;if (isFinished() && (readListener != null)) {try {readListener.onAllDataRead();} catch (IOException ex) {readListener.onError(ex);throw ex;}}return i;} else {return -1;}}};}@Overridepublic BufferedReader getReader() throws IOException {ByteArrayInputStream is = new ByteArrayInputStream(bytes);BufferedReader temp = new BufferedReader(new InputStreamReader(is));return temp;}
}
2.通用的过滤器
唯一可以自定义的地方就是步骤2中的敏感词列表,可以自己从mysql中查出一个list,然后用迭代器或for循环来挨个比对替换
//全局拦截
@WebFilter(urlPatterns = "/*",filterName = "AvoidFilter")
//Order数为最小int,全局最优先执行
@Order(-2147483648)
public class AvoidFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}/***这是第一个Filter拦截器,需要将 ServletRequest request对象传给MyHttpServletRequestWrapper* 然后调用getInputStream (会调用MyHttpServletRequestWrapper中重写的方法:多态性)* 此后网络流中的数据就在MyHttpServletRequestWrapper中持久化为了byte[] bytes* 从第二个Filter开始,其ServletRequest对象就是MyHttpServletRequestWrapper*/@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//1.多态转化 new MyHttpServletRequestWrapper的同时,输入流被持久化到了bytes中MyHttpServletRequestWrapper myHttpServletRequest = new MyHttpServletRequestWrapper((HttpServletRequest) request);HttpServletResponse httpServletResponse = (HttpServletResponse) response;//2.模拟敏感词过滤byte[] bytes = myHttpServletRequest.bytes;String s = IOUtils.toString(bytes, "UTF-8");/*** 这里一定要写成这种格式,因为replace()返回的是一个新的值*/s = s.replaceAll("傻逼","**");s = s.replaceAll("nmsl","**");byte[] newBytes = s.getBytes(StandardCharsets.UTF_8);myHttpServletRequest.bytes = newBytes;//3.链路调用chain.doFilter(myHttpServletRequest,httpServletResponse);}@Overridepublic void destroy() {Filter.super.destroy();}
}
3.测试
@PostMapping("/web")public DtoRes webTest(HttpServletRequest request , HttpServletResponse response ,@RequestBody DtoReq dtoReq) throws IOException {System.out.println(dtoReq);return null;}
postman发送请求:
在controller中@RequestBody所获取的信息:
SpringBoot通用的敏感词拦截相关推荐
- SpringBoot使用前缀树实现敏感词的过滤
记录一下使用SpringBoot中使用前缀树对敏感词的一个过滤. 首先呢在resources目录下建立一个文件用来装敏感词例如我在resources/sensitive-words.txt如下: 敏感 ...
- 网站是怎么屏蔽脏话的呢:简单学会SpringBoot项目敏感词、违规词过滤方案
一个社区最重要的就是交流氛围与审查违规,而这两者都少不了对于敏感词进行过滤的自动维护措施.基于这样的措施,我们才能基本保证用户在使用社区的过程中,不至于被敏感违规词汇包围,才能够正常的进行发布帖子和评 ...
- flex java 全局拦截_flex + java 过滤敏感词
过滤敏感词这个相对比较容易做到,网上也很多方法,看得比较多的一个方法就是:把所有的敏感词写入到一个properties文件中,程序启动时拼成一个正则表达式.这个也只是比较基础的敏感词过滤器,比较强大的 ...
- java过滤器敏感字的拦截_【JavaWeb】94:如何屏蔽敏感词?
今天是刘小爱自学Java的第94天. 感谢你的观看,谢谢你. 话不多说,开始今天的学习: 一.用户评论功能 网络上很多平台都会有敏感词屏蔽,有些词语打出来会被和谐掉. 虽说现在主张言论自由,但我大中华 ...
- SpringBoot使用SensitiveWord实现敏感词过滤
包含默认敏感词过滤和自定义敏感词过滤. 导入依赖 <dependency><groupId>com.github.houbb</groupId><artifa ...
- SpringBoot使用前缀树过滤敏感词
前缀树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利 ...
- SpringBoot之敏感词过滤
1. 功能描述 利用前缀树这种数据结构,设计并开发出敏感词过滤工具. 2. 构建敏感词表 resource/sensitive-words.txt 赌博 嫖娼 吸毒 开票 3. 敏感词过滤器 util ...
- 很全的敏感词匹配系统的设计与实践
作者:vivo互联网服务器团队-Liang Kangwu 一.前言 谛听系统是vivo的内容审核平台,保障了vivo各互联网产品持续健康的发展.谛听支持审核多种内容类型,但日常主要审核的内容是文本,下 ...
- spring boot 使用DFA算法实现敏感词过滤
spring boot 使用DFA算法实现敏感词过滤 敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的. DFA算法简介 DFA全称为:Deterministi ...
- 敏感词过滤,PHP实现的Trie树
[转载]敏感词过滤,PHP实现的Trie树 原文地址:http://blog.11034.org/2012-07/trie_in_php.html 项目需求,要做敏感词过滤,对于敏感词本身就是一个CR ...
最新文章
- linux cuda 如何编译器,linux – Cuda编译器不使用GCC 4.5
- Programming Pearls Essay 01
- ML之LiRLasso:基于datasets糖尿病数据集利用LiR和Lasso算法进行(9→1)回归预测(三维图散点图可视化)
- jenkins配置小结
- php header运用细节
- Win下通过 Navica t连接Ubuntu下MySQL数据库
- python logger_Python:logging 的巧妙设计!
- 20180513 实参 形参 数组
- 计算机插本2a院校,广东省专插本2A院校有哪些
- PRML 十大经典机器学习算法
- ni数据采集卡C语言API接口,NI数据采集卡
- mysql describe 作为字段_mysql中的describe语法 以及查看 当前库中所有表和字段信息...
- matlab线性规划求解函数:linprog
- ubuntu18.04: 安装nanomsg
- 在定语从句中which和that用法有什么区别
- Word基础(三十八)插入书签
- 数字信号处理(自学篇)
- 2018.7.18 上半年课程总结 4- 高级英语
- VMware View中智能卡和证书身份验证
- java for循环 等待_在forEach循环中使用异步/等待