一、xss攻击

XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。

简单说就是说,通过在输入框输入一些js代码,如在账号密码输入框中输入

<video src=1 onerror=alert(/xss/)/>

或者

 <script>alert("@@") </script>

这样点击提交的时候就会触发alert弹窗,分别弹出 xss  和 @@ 的内容,这里只是做个简单的演示,弹了个窗口,还能存储病毒下载地址到服务端,进入的时候自动下载,或者修改你的cookie啥的,这里感兴趣可以百度查查xss攻击。

二、如何防御

解决思路对用户提交表单的参数进行转移,如把< 转换为 &lt;  把 > 转换为 &rt;

java有很多的过滤工具类

<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>

然后通过下面的代码即可过滤

StringEscapeUtils.escapeHtml(string); 

底层也是将一切标签进行转移,达到js调用不生效的作用。

这里使用的是filter过请求进行拦截处理。

过滤的内容报过get请求的参数、对象, post形式body中的参数

1)添加xss过滤器

        <!-- xss过滤器 -->
<filter>
<filter-name>XssgFilter</filter-name>
<filter-class>com.train.web.filter.XssFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XssgFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

这里过滤了所有的请求,其中XssFilter是我们自己过滤器

2)添加自己的过滤器,

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException; public class XssFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
XssHttpServletRequestWrapper req=new XssHttpServletRequestWrapper((HttpServletRequest)servletRequest); filterChain.doFilter(req,servletResponse);
} @Override
public void destroy() { }
}

3)定义自己的http包装类

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
boolean isUpData = false;//判断是否是上传 上传忽略
public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
String contentType = servletRequest.getContentType ();
if (null != contentType)
isUpData =contentType.startsWith ("multipart");
} @Override
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values==null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = cleanXSS(values[i]);
}
return encodedValues;
} @Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return cleanXSS(value);
} /**
* 获取request的属性时,做xss过滤
*/
@Override
public Object getAttribute(String name) {
Object value = super.getAttribute(name);
if (null != value && value instanceof String) {
value = cleanXSS((String) value);
}
return value;
} @Override
public String getHeader(String name) { String value = super.getHeader(name);
if (value == null)
return null;
return cleanXSS(value);
}
private static String cleanXSS(String value) {
value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
value = value.replaceAll("%3C", "&lt;").replaceAll("%3E", "&gt;");
value = value.replaceAll("\\(", "(").replaceAll("\\)", ")");
value = value.replaceAll("%28", "(").replaceAll("%29", ")");
value = value.replaceAll("'", "'");
value = value.replaceAll("eval\\((.*)\\)", "");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
value = value.replaceAll("script", "");
return value;
} @Override
public ServletInputStream getInputStream () throws IOException {
if (isUpData){
return super.getInputStream ();
}else{ final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ()); return new ServletInputStream() { @Override
public int read() throws IOException {
return bais.read();
} @Override
public boolean isFinished() {
return false;
} @Override
public boolean isReady() {
return false;
} @Override
public void setReadListener(ReadListener readListener) { }
};
} }
public String inputHandlers(ServletInputStream servletInputStream){
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader (servletInputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (servletInputStream != null) {
try {
servletInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return cleanXSS(sb.toString ());
}
}

但是这里有个问题,假如这里还有一些特殊的需求,有些html标签是希望在前端能显示的,前端通过一些已经防止了xss攻击的富文本控件输入信息,后台不希望将这些信息转义

三、添加一些额外的内容

1)希望能动态的开关

2)期待部分接口的接口的参数是能存在标签的

添加一个xss开关的控制类, 这里使用了配置中心

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component
public class XSSFilterConfigUtil { public static Boolean openXssProtect; public static Boolean getOpenXssProtect() {
return openXssProtect == null ? false : openXssProtect;
} @Value("${open.xss.protect}")
public void setOpenXssProtect(Boolean openXssProtect) {
XSSFilterConfigUtil.openXssProtect = openXssProtect;
} }

注意的是:

  1. @Value无法为静态属性注入值,所以需要添加set方法为其注入值;

  2. 工具类必须添加@Component或者@Service注解,否则@Value不起作用。

静态方法中注入了值以后,Filter中就可以直接使用了。

修改上面的http包装类,这里不对" 进行过滤,过滤的话,会把json的""个去除,使用@RequestBody没办法解析成为一个正常的对象

import com.alibaba.fastjson.JSONObject;
import com.train.service.impl.XSSFilterConfigUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* 防护http处理
* 1.过滤xss
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { private static final Logger LOGGER = LoggerFactory.getLogger(XssHttpServletRequestWrapper.class); boolean isUpData = false;//判断是否是上传 上传忽略 //不期待被过滤的的链接和字段(管理后台使用了富文本,希望有可编辑的内容)
HashMap<String, String> doNotFilterURLAndParamMap = new HashMap<String, String>() {
{
put("/api/v2/group/manage", "description");
put("/api/v1/sendNews", "content"); }
}; /**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
* @throws IllegalArgumentException if the request is null
*/
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
String contentType = request.getContentType ();
if (null != contentType)
isUpData =contentType.startsWith ("multipart");
} /**
* 过滤单个参数
* @param name
* @return
*/
@Override
public String getParameter(String name) {
String parameter = super.getParameter(name);
if(StringUtils.isNotBlank(parameter) && XSSFilterConfigUtil.getOpenXssProtect()){
//这里使用的阿帕奇的common-lang3中的转义html方法,也可以自己实现,
String escapeParameter = this.cleanXSS(parameter);
return escapeParameter;
}
return parameter;
} /**
* 过滤实体的每个参数
* @param name
* @return
*/
@Override
public String[] getParameterValues(String name) { String[] parameterValues = super.getParameterValues(name);
if (parameterValues == null) {
return null;
}
if (XSSFilterConfigUtil.getOpenXssProtect()) {
for (int i = 0; i < parameterValues.length; ++i) {
String value = parameterValues[i];
parameterValues[i] = this.cleanXSS(value);
}
} return parameterValues; } /**
* 处理@RequestBody的形式传入的json数据
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream () throws IOException {
if(!XSSFilterConfigUtil.getOpenXssProtect()) {
return super.getInputStream ();
} if (isUpData){
return super.getInputStream ();
}else{ final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ()); return new ServletInputStream() { @Override
public int read() throws IOException {
return bais.read();
}
};
} } public String inputHandlers(ServletInputStream servletInputStream){
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (servletInputStream != null) {
try {
servletInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} String requestUrl = StringUtils.replaceOnce(this.getRequestURI(), this.getContextPath(), StringUtils.EMPTY);
boolean needFilter = false;
String key = "";
String param = "";
for(Map.Entry<String, String> entry : doNotFilterURLAndParamMap.entrySet()){ key = entry.getKey(); int index = StringUtils.indexOf(key, "*");
if (index > 0) {
String[] array = key.split("\\*");
StringBuffer stringBuffer = new StringBuffer();
for (String s : array) {
stringBuffer.append(s).append("(.*)");
}
Pattern p = Pattern.compile(stringBuffer.toString());
Matcher m = p.matcher(requestUrl);
if (m.find()) {
needFilter = true;
param = entry.getValue();
break;
}
} else {
if (requestUrl.equals(key)) {
needFilter = true;
param = entry.getValue();
break;
}
}
} if(needFilter) { //有需要特殊处理的字段,不希望过滤标签
try {
/*String param = doNotFilterURLAndParamMap.get(requestUrl);*/
JSONObject jsonObject = JSONObject.parseObject(sb.toString());
if(jsonObject.containsKey(param)) {
Object notFilterValue = jsonObject.get(param);
String cleanXSSParams = cleanXSS(sb.toString ());
JSONObject filteredJson = JSONObject.parseObject(cleanXSSParams);
filteredJson.put(param, notFilterValue);
return filteredJson.toJSONString();
}else {
return cleanXSS(sb.toString ());
} }catch (Exception e) {
LOGGER.error("XssHttpServletRequestWrapper转换json数据失败",e);
return cleanXSS(sb.toString ()); //异常时,就直接过滤,不管需要特殊处理的参数
} }else {
return cleanXSS(sb.toString ());
}
} /**
* 过滤规则,这里不直接使用StringEscapeUtils.escapeHtml,因为获取的是一个json字符串,会将" 替换导致数据异常,没有""进行分割,无法正常注入到@RequestBody
* @param value
* @return
*/
private static String cleanXSS(String value) {
value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
value = value.replaceAll("%3C", "&lt;").replaceAll("%3E", "&gt;");
// value = value.replaceAll("\\(", "(").replaceAll("\\)", ")");
value = value.replaceAll("%28", "(").replaceAll("%29", ")");
// value = value.replaceAll("'", "'");
/* value = value.replaceAll("eval\\((.*)\\)", "");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
value = value.replaceAll("script", "");*/
return value;
} }

java 拦截器解决xss攻击的更多相关文章

  1. 记一次JAVA WEB项目解决XSS攻击的办法(亲测有效)

    什么是XSS攻击 简单来说,XSS 攻击是页面被注入了恶意的代码,度娘一大堆的东西,不想说 系统架构主要是SSM框架,服务层另外使用了DubboX.   为啥说这个,因为SpringMVC对于Xss攻 ...

  2. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 >>>>>>>>>>>>>>&g ...

  3. spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,guava限流,定时任务案例, 发邮件

    本文介绍spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,定时任务案例 集成swagger--对于做前后端分离的项目,后端只需要提供接口访问,swagger提供了接口 ...

  4. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求   Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 java ...

  5. java 拦截器

    一.前言 这是一篇关于 java 拦截器的文章,是我的写 java  web 所遇见的问题.当我们写好一个网站,必须要通过登陆页面才可以进入这个系统.那么我们就得写个 java 拦截器,如果是通过登录 ...

  6. 拦截过滤防御XSS攻击 -- Struts2.3 以及 2.5 的解决方式

    使用Struts2框架开发的后台在防御XSS攻击的时候很多方式都不能用,因为Struts2对请求进行的二次封装有区别.以下针对Struts2的XSS攻击进行拦截过滤防御解决: Struts2.3 本方 ...

  7. Spring mvc拦截器防御CSRF攻击

    CSRF(具体参考百度百科) CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSR ...

  8. Java Web学习(十)Java拦截器

    文章更新时间:2020/04/07 一.引言 既然要用拦截器,首先先得简单了解一下什么是拦截器: 概念:java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Actio ...

  9. java 拦截器和过滤器区别(转载)

    1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的 ...

随机推荐

  1. Nginx是如何处理一个请求

    首先,nginx在启动时,会解析配置文件,得到需要监听的端口与ip地址,然后在nginx的master进程里面,先初始化好这个监控的socket(创建socket,设置addrreuse等选项,绑定到 ...

  2. 第7章 PCA与梯度上升法

    主成分分析法:主要作用是降维 疑似右侧比较好? 第三种降维方式: 问题:????? 方差:描述样本整体分布的疏密的指标,方差越大,样本之间越稀疏:越小,越密集 第一步: 总结: 问题:????怎样使其 ...

  3. 微软Azure IoT驱动数字化变革线上分享会(6月4号)

    微软Azure IoT驱动数字化变革线上分享会(6月4号)   微软作为全球范围内IoT领域的领军者,以微软智能云Azure为基础和核心,推动包括物联网.机器学习.微服务.人工智能等在内的新技术的发展 ...

  4. 使用 IdentityService4 集成小程序登录一种尝试

    1 场景介绍 主要业务是通过 App 承载,在 App 中可以注册和登录,为了更好的发展业务引入了微信小程序,于是如何让这两个入口的用户互通便成了需要解决的问题. 看了一下其它 App 大致地思路是两 ...

  5. Element Form表单实践(下)

    作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...

  6. [Office#PPT]0001.实例剖析-如何制作一个牛B的融资PPT

    一些好公司明明在模式上富有创新性,但却在 pitch 时很保守,而且他们又不缺设计和开发能力.如何设计你的融资演讲稿才会吸引投资人对你投资?投资人 Daniel Eckler给大家贡献了下面这篇技术贴 ...

  7. IT笑话十则(一)

    一.下班前发给你 客户:“这个图下班之前必须发给我!” 设计师:“好的!” 第二天清早. 客户:“图怎么还没发过来?” 设计师:“我还没下班呢…”   二.受伤的老三 行业老大与老二PK,受伤的并非对 ...

  8. CSS 风车(花瓣)旋转动画圆角

    这是一个综合的案例,用到了transition(动画,动作在单位时间内完成),transform(旋转),border-radius(圆角),absolute(定位),linear-gradient( ...

  9. centos6.4中文输入法

    在虚拟机中装了centos6.4之后,一直使用命令行,没有用到编辑器编辑中文或者浏览器中文搜索,所以没有注意到里边中文输入的重要性.在网上有看到说如果用的是中文版本应该有自带的中文输入法,然后用快捷键 ...

  10. ROS入门笔记(二):ROS安装与环境配置及卸载(重点)

    ROS入门笔记(二):ROS安装与环境配置及卸载(重点) [TOC] 1 ROS安装步骤 1.1 ROS版本 ROS目前只支持在Linux系统上安装部署, 它的首选开发平台是Ubuntu. 发布时间 ...