抵御即跨站脚本(XSS)攻击
XSS攻击通常指的是通过利用网站系统保存系统的漏洞,通过巧妙的方法把恶意指令注入到网页,用户加载网页的时候会自动执行恶意脚本
比如:
<script>
alert(xss);
</script>
如果客户能在你的浏览器执行javascript,那么就能窃取cookie或者token。
1.pom.xml添加 依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.14</version>
</dependency>
可以查看hutool的知识点
HTML工具类-HtmlUtil · Hutool 参考文档
2.在自己的com.xxx.filter.xss包新建类XssHttpServletRequestWrapper
package com.xxxx.filter.xss;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* 声明子类的构造器
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if(!StrUtil.hasEmpty(value)) {
//把一些带script标签的 过滤掉,变成普通文本 HtmlUtil.filter 过滤HTML文本,防止XSS攻击
value = HtmlUtil.filter(value);
}
//然后可以安全的保存到数据库里面的
return value;
}
/**
* 把返回的参数也进行转义
* @param name
* @return
*/
@Override
public 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)){
//把一些带script标签的 过滤掉,变成普通文本 HtmlUtil.filter 过滤HTML文本,防止XSS攻击
value = HtmlUtil.filter(value);
}
values[i] = value;
}
}
//然后可以安全的保存到数据库里面的
return values;
}
/**
* 把请求中的数据返回一个map对象,也要做一下转义
* @return
*/
@Override
public 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);
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (!StrUtil.hasEmpty(value)) {
//HtmlUtil.filter 过滤HTML文本,防止XSS攻击
value = HtmlUtil.filter(value);
}
values[i] = value;
}
map.put(key,values);
}
}
return map;
}
/**
* 从请求头获取到数据 也要做一下转义
* @param name
* @return
*/
@Override
public String getHeader(String name) {
String value= super.getHeader(name);
if (!StrUtil.hasEmpty(value)) {
//HtmlUtil.filter 过滤HTML文本,防止XSS攻击
value = HtmlUtil.filter(value);
}
return value;
}
/**
* 通过io流 读取数据 也要做一下转义
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException {
InputStream in= super.getInputStream();
InputStreamReader reader=new InputStreamReader(in, Charset.forName("UTF-8"));
BufferedReader buffer=new BufferedReader(reader);
StringBuffer body=new StringBuffer();
String line=buffer.readLine();
while(line!=null){
body.append(line);
line=buffer.readLine();
}
buffer.close();
reader.close();
in.close();
Map<String,Object> map=JSONUtil.parseObj(body.toString());
Map<String,Object> result=new LinkedHashMap<>();
for(String key:map.keySet()){
Object val=map.get(key);
if(val instanceof String){
if(!StrUtil.hasEmpty(val.toString())){
//转义
result.put(key,HtmlUtil.filter(val.toString()));
}
}
else {
//不需要转义的数据
result.put(key,val);
}
}
//又转成json的字符串
String json=JSONUtil.toJsonStr(result);
ByteArrayInputStream bain=new ByteArrayInputStream(json.getBytes());
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bain.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
3. 再建个XssFilter
package com.xxxx.filter.xss;
/**
* urlPatterns = "/*"表示所有请求路由都需要拦截的
*/
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
XssHttpServletRequestWrapper wrapper = new XssHttpServletRequestWrapper(request);
//通过后 继续往下执行 放行
filterChain.doFilter(wrapper,servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
4. 最后一步是在启动文件里加上
@ServletComponentScan
5. 启动
6. 最后后端会把<script>标签过滤掉。
得出的结果是
alert(xxxxx);
7. 但是呢,同时也把html的标签也过滤掉了,我不想过滤掉html标签。
未完后续....