Java使用过滤器防止SQL注入XSS脚本注入的实现

前几天有个客户在系统上写了一段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。因此我们只需要在定义过滤器时,先获取请求头判断是否为文件上传,若是再对数据进行解析便可。

到此这篇关于Java使用过滤器防止SQL注入XSS脚本注入的实现的文章就介绍到这了,更多相关Java 过滤器防止SQL注入 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java持久层框架mybatis防止sql注入的方法

    sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如"or '1'='1'"这样的语句,有可能入侵参数校验不足的应用程序.所以在我们的应用中需要做一些工作,来防备这样的攻击方式.在一些安全性很高的应用中,比如银行软件,经常使用将sql语句全部替换为存储过程这样的方式,来防止sql注入,这当然是一种很安全的方式,但我们平时开发中,可能不需要这种死板的方式. mybatis框架作为一款半自动化的持久层框架,其sql语句都要我们自己来手

  • Java面试题解析之判断以及防止SQL注入

    本文研究的主要是Java面试题中的一个比较常见的题目,判断及防止SQL注入的问题,具体介绍如下. SQL注入是目前黑客最常用的攻击手段,它的原理是利用数据库对特殊标识符的解析强行从页面向后台传入.改变SQL语句结构,达到扩展权限.创建高等级用户.强行修改用户资料等等操作. 那怎么判断是否被SQL注入了呢? 通过SQL注入的原理我们知道,判断SQL注入可以通过页面传入的数据,后台不应该相信从后台传入的任何数据特别是特殊整型参数和特殊字符参数! 防止SQL注入其实也很简单 1.检查变量数据类型和格式

  • Java使用过滤器防止SQL注入XSS脚本注入的实现

    前几天有个客户在系统上写了一段html语句,打开页面就显示一张炒鸡大的图片,影响美观.后来仔细想想,幸亏注入的仅仅是html语句,知道严重性后,马上开始一番系统安全配置. 一. 定义过滤器 package com.cn.unit.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; i

  • springboot中使用过滤器,jsoup过滤XSS脚本详解

    目录 springboot使用过滤器,jsoup过滤XSS脚本 1.把可能包含脚本的参数位置分析一下 2.分析实现过程 3.代码实现过程 使用jsoup防止XSS攻击 springboot使用过滤器,jsoup过滤XSS脚本 背景:略 目标:完成request请求中的脚本过滤 技术:filter,jsoup,requestWapper 1.把可能包含脚本的参数位置分析一下 post/put/delete: 请求的参数中,有可能是表单提交.也有可能是使用了@requestBody注解,那么参数就是

  • JSP使用过滤器防止SQL注入的简单实现

    什么是SQL注入攻击?引用百度百科的解释: sql注入_百度百科: 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句.[1]  比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这

  • Java如何防止JS脚本注入代码实例

    1.java中防止JS脚本注入的工具类-通用 public class XssUtil { private static Map<String, String> xssMap = new LinkedHashMap<String, String>(); private static Map<String, String> xssNewMap = new LinkedHashMap<String, String>(); static { init(); } p

  • Java中如何避免sql注入实例详解

    目录 前言 造成sql注入的原因: 预防sql注入方法: java 有效的防止SQL注入 总结 前言 sql注入是web开发中最常见的一种安全漏洞.可以用它来从数据库获取敏感信息.利用数据库的特性执行添加用户.导出文件等一系列恶意操作,甚至有可能获取数据库乃至系统用户最高权限. 造成sql注入的原因: 程序没有有效过滤用户的输入,使攻击者成功的向服务器提交恶意的SQL脚本,程序在接收后错误的将攻击者的输入作为SQL语句的一部分执行,导致原始的查询逻辑被改变,执行了攻击者精心构造的恶意SQL语句.

  • 一文搞懂Java JDBC中的SQL注入问题

    目录 SQL注入 什么是SQL注入 SQL注入的效果的演示 SQL注入代码 SQL注入效果 如何避免SQL注入 PrepareStatement解决SQL注入 PreparedStatement的应用 参数标记 动态参数绑定 综合案例 PreparedStatement总结 必须使用Statement的情况 SQL注入 什么是SQL注入 在用户输入的数据中有SQL关键字或语法,并且关键字或语法参与了SQL语句的编译.导致SQL语句编译后的条件为true,一直得到正确的结果.这种现象就是SQL注入

  • SQL Injection with MySQL 注入分析

    声明 本文仅用于教学目的,如果因为本文造成的攻击后果本人概不负责,本文所有代码均为本人所写,所有数据均经过测试.绝对真实.如果有什么遗漏或错误,欢迎来安全天使论坛和我交流. 前言 2003年开始,喜欢脚本攻击的人越来越多,而且研究ASP下注入的朋友也逐渐多了起来,我看过最早的关于SQL注入的文章是一篇99年国外的高手写的,而现在国外的已经炉火纯青了,国内才开始注意这个技术,由此看来,国内的这方面的技术相对于国外还是有一段很大差距,话说回来,大家对SQL注入攻击也相当熟悉了,国内各大站点都有些堪称

  • Java中过滤器 (Filter) 和 拦截器 (Interceptor)的使用

    1.过滤器 (Filter) 过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法. init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次.注意:这个方法必须执行成功,否则过滤器会不起作用. doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter. destroy(): 当容器销毁 过滤器

  • 基于java servlet过滤器和监听器(详解)

    1 过滤器 1.过滤器是什么? servlet规范当中定义的一种特殊的组件,用于拦截容器的调用. 注:容器收到请求之后,如果有过滤器,会先调用过滤器,然后在调用servlet. 2.如何写一个过滤器? 1.写一个java类,实现Filter接口; 2.在接口方法中实现拦截方法; 3.配置过滤器(web.xml); 3.配置初始化参数 1.配置初始化参数.(init-param) 2.通过filterconfig提供的getinitparamenter方法读取初始化的值. 4.优先级: 当有多个过

  • 深入解析Java的Spring框架中bean的依赖注入

    每一个基于java的应用程序都有一个共同工作来展示给用户看到的内容作为工作的应用几个对象.当编写一个复杂的Java应用程序,应用程序类应该尽可能独立其他Java类来增加重复使用这些类,并独立于其他类别的测试它们,而这样做单元测试的可能性.依赖注入(或有时称为布线)有助于粘合这些类在一起,同时保持他们的独立. 考虑有其中有一个文本编辑器组件的应用程序,要提供拼写检查.标准的代码将看起来像这样: public class TextEditor { private SpellChecker spell

随机推荐