[JavaWeb]_[初级]_[对Html特殊符号进行转义防止XSS攻击和反转义]
Posted infoworld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaWeb]_[初级]_[对Html特殊符号进行转义防止XSS攻击和反转义]相关的知识,希望对你有一定的参考价值。
场景
- 在开发
Java Web
程序时,为了防止XSS
的javascript
攻击, 需要对用户输入转义,使JavaScript
脚本不能执行. 在前端可以通过获取<div>
的innerhtml
属性来获取转义内容,但是在服务端如何进行转义?因为客户端是可以绕过的.
说明
-
HTML
内容的转义在开发Web
时肯定是必须做的,在入数据库之前得转义,而不是在用的时候再转义。主要是防止在使用这类数据的时候忘记没有转义导致的XSS
安全问题. -
转义
HTML
字符主要涉及到5
个字符<>"'&
,所以只需要转义这几个即可。要实现转义字符,最基本的做法就是通过逐个分析String
里的字符,之后使用转移字符串替换. 看htmlEscape1()
方法即是最基本的做法。而另一种做法就是使用htmlEscape2()
,它之前讲过的使用正则高效替换字符串的多个占位符为多个值[3]. 这两种方法在进行测试执行时间的时候方法1更快,可见正则匹配更耗费时间。
输出
package com.example.string;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
public class HtmlEscapeTest{
public static String htmlEscape1(String str) {
if(isEmpty(str))
return str;
StringBuilder w = new StringBuilder();
for (int i = 0, len = str.length(); i < len; i++) {
char cur = str.charAt(i);
switch (cur) {
case '<':
w.append("<");
break;
case '>':
w.append(">");
break;
case '"':
w.append(""");
break;
case '\\'':
w.append("'");
break;
case '&':
w.append("&");
break;
default:
w.append(cur);
break;
}
}
return w.toString();
}
private static boolean isEmpty(String str) {
return str == null || str.isEmpty();
}
/**
*
* StringBuilder sb = new StringBuilder();
* HashMap<String, String> oldToNew = new HashMap<>();
* oldToNew.put("$sn",sn);
* oldToNew.put("$email",mail);
* StringUtils.replaceOneMore(sb,registertemplate,"[$]sn|[$]email",oldToNew);
*
* @param output
* @param input
* @param oldRegex
* @param oldToNew
*/
public static void replaceOneMore(StringBuilder output, String input,
String oldRegex, Map<String,String> oldToNew){
Pattern p = Pattern.compile(oldRegex);
Matcher m = p.matcher(input);
while (m.find()) {
String one = m.group();
if(oldToNew.containsKey(one))
m.appendReplacement(output, oldToNew.get(one));
}
m.appendTail(output);
}
public static String htmlEscape2(String source){
if(isEmpty(source))
return source;
StringBuilder builder = new StringBuilder();
HashMap<String, String> oldToNew = new HashMap<>();
oldToNew.put("<","<");
oldToNew.put(">",">");
oldToNew.put("\\"",""");
oldToNew.put("'","'");
oldToNew.put("&","&");
long start2 = System.currentTimeMillis();
replaceOneMore(builder,source,"[<]|[>]|[\\"]|[']|[&]",oldToNew);
long end2 = System.currentTimeMillis();
print("replaceOneMore",end2-start2);
return builder.toString();
}
public static String htmlUnescape(String str){
if(isEmpty(str))
return str;
if(str.indexOf("&") == -1)
return str;
StringBuilder sb = new StringBuilder();
HashMap<String, String> oldToNew = new HashMap<>();
oldToNew.put("<","<");
oldToNew.put(">",">");
oldToNew.put(""","\\"");
oldToNew.put("'","\\'");
oldToNew.put("&","&");
replaceOneMore(sb,str,"[&]lt;|[&]gt;|[&]quot;|[&]#39;|[&]amp;",oldToNew);
return sb.toString();
}
public static<T> void print(String key,T t){
System.out.println(key +" : "+t);
}
@Test
public void testEscapeHtml(){
String str = "<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&"
+"<a href=\\"http://blog.csdn.net/infoworld?name=tobey&year=2021\\"></a><script>alert('hello')</script>&";
long start1 = System.currentTimeMillis();
String result1 = htmlEscape1(str);
long old1 = System.currentTimeMillis();
print("result1",result1);
print("duration",old1-start1);
long start2 = System.currentTimeMillis();
String result2 = htmlEscape2(str);
long end2 = System.currentTimeMillis();
print("result2",result2);
print("duration",end2-start2);
assertEquals(result2, result1);
String source = htmlUnescape(result2);
assertEquals(source, str);
print("source",source);
}
}
输出
result1 : <a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&
duration : 1
replaceOneMore : 8
result2 : <a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&
duration : 8
source : <a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&<a href="http://blog.csdn.net/infoworld?name=tobey&year=2021"></a><script>alert('hello')</script>&
参考
以上是关于[JavaWeb]_[初级]_[对Html特殊符号进行转义防止XSS攻击和反转义]的主要内容,如果未能解决你的问题,请参考以下文章
[JavaWeb]_[初级]_[对Jfinal框架的Controller进行单元测试]
[JavaWeb]_[初级]_[对Jfinal框架的Controller进行单元测试]
[JavaWeb]_[初级]_[对Jfinal框架的Service层进行单元测试]
[JavaWeb]_[初级]_[对Jfinal框架的Service层进行单元测试]