xss 攻击不再介绍。
1. 创建自定义注解@NoXss,主要是方法和参数上。
2. 判断参数对象中的带有注解@NoXss 并且是字符串类型,将字符串转码为非html 的代码。
1. 创建自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD, ElementType.FIELD })
public @interface NoXss {
}
2. 创建切面
import java.lang.reflect.Field;
import java.util.Arrays;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.util.HtmlUtils;
@Aspect
@Component
public class NoXssAspect {
@Around("@annotation(noXss)")
public Object beforeMethod(ProceedingJoinPoint joinPoint, NoXss noXss) throws Throwable {
// 通过类反射拿到所有参数
Object[] args1 = joinPoint.getArgs();
if (args1.length == 0) {
return joinPoint.proceed();
}
for (int i = 0; i < args1.length; i++) {
JSONObject jsonObject = JSONUtil.parseObj(args1[i]);
// 通过类反射拿到所有变量
Field[] fields = args1[i].getClass().getDeclaredFields();
if (fields.length == 0) {
continue;
}
Arrays.stream(fields).filter(
field -> field.isAnnotationPresent(NoXss.class) && field.getType() == String.class).forEach(p -> {
// 修改joinPoint.getArgs()的值
String value = jsonObject.getStr(p.getName());
//
if (value != null && value.length() != 0) {
jsonObject.set(p.getName(), filterHtmlTags(value));
}
});
args1[i] = jsonObject.toBean(args1[i].getClass());
}
return joinPoint.proceed(joinPoint.getArgs());
}
private String filterHtmlTags(String input) {
// 使用Jsoup过滤HTML,只允许安全的标签和属性
return HtmlUtils.htmlEscape(input);
}
}
3. 验证:
@RestController
public class TzTestController {
@NoXss
@PostMapping("/noXss")
public ResultVo<String> noXss(@RequestBody TzTestVo vo) {
return ResultVo.success(vo.getName());
}
}
TzTestVo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TzTestVo {
@NoXss
private String name;
}
效果就是:
{
"name": "<script>alert(\"hello XSS\")</script>"
}
目前问题:
1. 只能验证参数的第一层。没有做递归处理。
2. 没有做报错异常处理。