参考:https://blog.csdn.net/jungeCSND/article/details/106408032
测试步骤:使用抓包工具,改变参数为:<script>alert('1');</script>
后保存提交。页面刷新后,可以弹出alert框。
感觉可以用过滤器来处理这个问题,暂时没找到合适的方法。后续在修改。
注:只添加了对String修饰的属性进行转换。
public class XssUtils implements Serializable {
private static final long serialVersionUID = 3915672532461661611L;
/**
* 对入参对象中用String修饰的属性值进行转换。(过滤类似于xss攻击问题)
* @param object 入参对象
*/
public static void res(Object object){
if (object != null) {
Field[] f = object.getClass().getDeclaredFields();
for (Field field : f) {
String attributeName = field.getName();
String methodName = attributeName.substring(0, 1).toUpperCase() + attributeName.substring(1);
boolean accessFlag = field.isAccessible();
try {
field.setAccessible(true);
if (getFieldValueByName(field.getName(), object)!=null){
if (field.getType() == String.class) {
Method setMethod = object.getClass().getMethod("set" + methodName, String.class);
Object o = field.get(object);
String n = xssEncode(o.toString());
setMethod.invoke(object, n);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
field.setAccessible(accessFlag);
}
}
}
}
/**
* 单一的字段转换
* @param s 转换字段
* @return 转换后
*/
public static String resString(String s){
if (StringUtils.isEmpty(s)) {
throw new NullPointerException("Conversion failed:"+s+" Is Null");
}
return xssEncode(s);
}
/**
* 获取对象值
* @param fieldName 对象的k
* @param o 对象
* @return 对象
*/
private static Object getFieldValueByName(String fieldName, Object o) {
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = o.getClass().getMethod(getter, new Class[] {});
Object value = method.invoke(o, new Object[] {});
return value;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static String xssEncode(String s) {
if (s == null || s.isEmpty()) {
return s;
}
StringBuilder sb = new StringBuilder(s.length() + 16);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '>':
sb.append('>');
break;
case '<':
sb.append('<');
break;
case '\'':
sb.append('‘');
break;
case '\"':
sb.append('“');
break;
case '&':
sb.append('&');
break;
case '\\':
sb.append('\');
break;
case '#':
sb.append('#');
break;
case '%':
processUrlEncoder(sb, s, i);
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}
public static void processUrlEncoder(StringBuilder sb,String s,int index){
if(s.length() >= index + 2){
if(s.charAt(index+1) == '3' && (s.charAt(index+2) == 'c' || s.charAt(index+2) == 'C')){
sb.append('<');
return;
}
if(s.charAt(index+1) == '6' && s.charAt(index+2) == '0'){
sb.append('<');
return;
}
if(s.charAt(index+1) == '3' && (s.charAt(index+2) == 'e' || s.charAt(index+2) == 'E')){
sb.append('>');
return;
}
if(s.charAt(index+1) == '6' && s.charAt(index+2) == '2'){
sb.append('>');
return;
}
}
sb.append(s.charAt(index));
}
}
Controller层调用的时候
/**
*入参是对象
*/
//注解就不加了
public class Json 方法名(入参对象 obj){
XssUtils.res(obj);
//下面就是你之后的操作了
.....
}
/**
*入参是单一的字段
*/
//注解就不加了
public class Json 方法名(HttpServletRequest request){
String 转换后的值 = XssUtils.resString(request.getParameter("K值"));
//下面就是你之后的操作了
.....
}