Java使用过滤器防止SQL注入XSS脚本注入的实现
作者:踮脚敲代码 发布时间:2021-09-14 18:17:19
标签:Java,过滤器,防止SQL注入
前几天有个客户在系统上写了一段html语句,打开页面就显示一张炒鸡大的图片,影响美观。后来仔细想想,幸亏注入的仅仅是html语句,知道严重性后,马上开始一番系统安全配置。
一. 定义过滤器
package com.cn.unit.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
/**
* 过滤器
* Created by adonis on 2020/12/12
*/
public class SafeFilter implements Filter{
// 配置信息对象
public FilterConfig filterConfig;
/**
* 初始化
* 与我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。
* Web应用程序启动时,Web服务器将创建Filter的实例对象,并调用其init方法,读取web.xml配置,
* 完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作。
* Filter对象只会创建一次,init方法也只会执行一次。
* 开发人员通过init方法的参数,可获得代表当前Filter配置信息的FilterConfig对象。
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterConfig = config;
}
/**
* 拦截请求
* 这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。
* FilterChain参数用于访问后续过滤器。
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String enctype = httpRequest.getContentType();
if(StringUtils.isNotBlank(enctype) && enctype.contains("multipart/form-data")){
// 上传文件
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
httpRequest.getSession().getServletContext());
MultipartHttpServletRequest multipartRequest = commonsMultipartResolver.resolveMultipart(httpRequest);
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(multipartRequest);
chain.doFilter(xssRequest, response);
}else{
// 普通表单和Ajax
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
}
/**
* 销毁
* Filter对象创建后会驻留在内存,当Web应用移除或服务器停止时才销毁。在Web容器卸载Filter对象之前被调用。
* 该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
*/
@Override
public void destroy() {
this.filterConfig = null;
}
}
二. 过滤包装器,实现参数值过滤
package com.cn.unit.filter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* 用户请求包装类
* Created by adonis on 2020/12/12
*/
public class SafeHttpServletRequestWrapper extends HttpServletRequestWrapper{
public SafeHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null) {
value = xssEncode(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] value = super.getParameterValues(name);
if(value != null){
for (int i = 0; i < value.length; i++) {
value[i] = xssEncode(value[i]);
}
}
return value;
}
@Override
public Map getParameterMap() {
return super.getParameterMap();
}
/**
* 请求头不过滤
*/
@Override
public String getHeader(String name) {
return super.getHeader(name);
}
/**
* 将容易引起注入的关键字的半角字符直接替换成全角字符
* @param value 过滤前的值
* @return 过滤后的值
*/
private static String xssEncode(String value) {
if (value == null || value.isEmpty()) {
return value;
}
// 防SQL注入转义
value = StringEscapeUtils.escapeSql(value);
// HTML防注入,个人建议使用第三种
// 1.防HTML注入转义(HtmlUtils工具类,汉字不转义,双引号转义,存在JSON封装需要反转义)
value = HtmlUtils.htmlEscape(value);
/*
// 2.防HTML注入转义(StringEscapeUtils工具类,汉字也转义,取出时需要反转义)
// value = StringEscapeUtils.escapeHtml(value);
// 3.字符串替换法(通过各种循环替换字符串测试,最终还是replace替换效果最佳)
value = value.replaceAll("<", "<");
value = value.replaceAll(">", ">");
value = value.replaceAll("'", "'");
value = value.replaceAll(";", "﹔");
value = value.replaceAll("&", "&");
value = value.replaceAll("%", "﹪");
value = value.replaceAll("#", "#");
value = value.replaceAll("select", "seleᴄt");// "c"→"ᴄ"
value = value.replaceAll("truncate", "trunᴄate");// "c"→"ᴄ"
value = value.replaceAll("exec", "exeᴄ");// "c"→"ᴄ"
value = value.replaceAll("join", "jᴏin");// "o"→"ᴏ"
value = value.replaceAll("union", "uniᴏn");// "o"→"ᴏ"
value = value.replaceAll("drop", "drᴏp");// "o"→"ᴏ"
value = value.replaceAll("count", "cᴏunt");// "o"→"ᴏ"
value = value.replaceAll("insert", "ins℮rt");// "e"→"℮"
value = value.replaceAll("update", "updat℮");// "e"→"℮"
value = value.replaceAll("delete", "delet℮");// "e"→"℮"
value = value.replaceAll("script", "sᴄript");// "c"→"ᴄ"
value = value.replaceAll("cookie", "cᴏᴏkie");// "o"→"ᴏ"
value = value.replaceAll("iframe", "ifram℮");// "e"→"℮"
value = value.replaceAll("onmouseover", "onmouseov℮r");// "e"→"℮"
value = value.replaceAll("onmousemove", "onmousemov℮");// "e"→"℮"*/
return value;
}
}
三. 配置web.xml添加过滤器
<!-- 配置过滤器防止SQL注入XSS注入 -->
<filter>
<filter-name>XssSqlFilter</filter-name>
<filter-class>com.cn.unit.filter.SafeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XssSqlFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
配置各节点简单介绍:
节点名 | 介绍 |
---|---|
<filter> | 指定一个过滤器 |
<filter-name> | 用于为过滤器指定一个名字,该元素的内容不能为空 |
<filter-class> | 指定过滤器的完整的限定类名 |
<init-param> | 为过滤器指定初始化参数。在过滤器中,可以使用FilterConfig接口对象来访问初始化参数 |
<param-name> | <init-param>的子元素,指定参数的名字 |
<param-value> | <init-param>的子元素,指定参数的值 |
<filter-mapping> | 设置一个Filter所负责拦截的资源。可通过Servlet名称或资源访问的请求路径指定 |
<filter-name> | 子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字 |
<url-pattern> | 设置 filter 所拦截的请求路径(过滤器关联的URL样式) |
<servlet-name> | 指定过滤器所拦截的Servlet名称 |
<dispatcher> | 指定过滤器所拦截的资源被 Servlet 容器调用的方式,默认REQUEST |
四. 静态资源跳过过滤
在实际开发的过程中,js、css等静态资源也进行过滤,消耗服务器性能,因此把一些不必要过滤的直接跳过过滤器,实现如下:
4.1 在web.xml配置文件中添加参数,保存静态资源所在的路径
<init-param>
<param-name>excludeFilter</param-name><!-- 静态资源不进行过滤,如js、css文件 -->
<param-value>/document/;/ligentres/</param-value>
</init-param>
如图:
4.2 过滤器初始化方法,读取静态资源所在的路径
public FilterConfig filterConfig;
public String[] excludeFilterArray;
@Override
public void init(FilterConfig config) throws ServletException {
filterConfig = config;
// 读取web配置文件中的静态资源所在路径
String excludeFilter = filterConfig.getInitParameter("excludeFilter");
excludeFilterArray = excludeFilter.split(";");
}
4.3 过滤器拦截请求,若是静态资源所在的路径直接跳过过滤器
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String uri = httpRequest.getRequestURI();
// 静态资源直接跳过,不进行过滤
if(uri==null||this.isContains(uri, excludeFilterArray)) {
chain.doFilter(request, response);
return;
}
......
}
// 判断数组是否包含某一元素
public boolean isContains(String uri, String[] regx) {
boolean result = false;
for (int i = 0; i < regx.length; i++) {
if (uri.indexOf(regx[i]) != -1) {
return true;
}
}
return result;
}
五. 大功告成
借鉴前人的经验,一开始测试的时候发现,普通的表单提交和ajax提交可以过滤其参数,但上传文件时就无法进入过滤了。
后来经过研究,用于处理文件上传的 MultipartResolver ,当收到请求时,DispatcherServlet 的 checkMultipart() 方法会调用 MultipartResolver 的 isMultipart() 方法判断请求中是否包含文件。如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest 对象中,最后传递给 Controller。因此我们只需要在定义过滤器时,先获取请求头判断是否为文件上传,若是再对数据进行解析便可。
来源:https://blog.csdn.net/ii950606/article/details/111323906


猜你喜欢
- 日志过滤对于一个网站日志,首先要对它进行过滤,删除一些不必要的信息,我们通过scala语言来实现,清洗代码如下,代码要通过别的软件打包为ja
- //创建excelobject missing = System.Reflection.Missing.Value;Excel.Applic
- 前言数据驱动测试是相同的测试脚本使用不同的测试数据执行,测试数据和测试行为完全分离。数据驱动是做自动化测试中很重要的一部分,数据源的方案也是
- AIDL是Android接口定义语言,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个
- 1.定义Token的注解,需要Token校验的接口,方法上加上此注解import java.lang.annotation.ElementT
- 在微信公众号里面需要上传头像,时间比较紧,调用学习jssdk并使用 来不及 就用了input1、使用input:file标签, 去调用系统默
- itextpdf解决PDF合并的问题本文章是我在项目开发过程中解决了一个关于PDF显示的需求而记录的。需求是这样的,需要将两个PDF进行合并
- 1.新建控制台应用程序2.新建类 EncryptHelper.cspublic static class EncryptHelper{ &n
- spring boot2.x已经出来好一阵了,而且spring cloud 的最新Release版本Finchley.RELEASE,默认集
- 这篇文章主要介绍了Mybatis模糊查询及自动映射实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- 本文实例讲述了C#使用iTextSharp从PDF文档获取内容的方法。分享给大家供大家参考。具体实现方法如下:using System;us
- 一、代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强。加入一些非业务性代码,比如事务、日志、报警发邮件等
- 1.AndroidManinifest.xml中加入权限<uses-permission android:name="and
- List集合相信大家在开发过程中几乎都会用到。有时候难免会遇到集合里的数据是重复的,需要进行去除。然而,去重方式有好几种方式,你用的是哪种方
- 前言:学习了SpringBoot分页查询的两种写法,一种是手动实现,另一种是使用框架实现。现在我将具体的实现流程分享一下。首先是手动实现分页
- 我们经常会使用springboot创建web应用,在springboot中金静态资源是如何存放的呢?静态资源映射规则我们先创建一个sprin
- 第一步:官网(或跟硬件开发WMI的人沟通你需要的接口和参数定义,如果是和硬件开发的人协定WMI接口,直接看第二步)查找你需要的WMI信息;举
- 将方形的图像映射到正方形上似乎并没有什么难度,所以接下来要做的是把图像映射到球面上。而球的参数方程为x=rcosϕcos&theta
- Spring框架基于注解开发CRUD,供大家参考,具体内容如下1. Maven坐标<!-- https://mvnrepository
- 本文实例为大家分享了android密码输入框效果展示的具体代码,供大家参考,具体内容如下老规矩,先看效果;这是现在商城类app中很常见的支付