SpringBoot去除参数前后空格和XSS过滤
去除XSS字符串需要借助工具类 jsoup ,这里jsoup有一点需要注意的是,jsoup的功能可能有点太强大了,能把xss攻击的内容直接过滤掉了不说,也会对英文尖括号<>转义,到接口里面拿到的参数就变成了<
>
,存库里面的就是转义后的字符串了。取出来的时候需要转一下。
比如前台传的参数传的是: 12<>3455
过滤处理了后,到后台接口里面就成了:[12<
>
3455]
如果上面的结果能接受,那么这个工具类就可以用。
引入依赖 jsoup
org.jsoup jsoup1.12.1
JsoupUtil.java工具类:
import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.safety.Whitelist; /** * * @Auther linmengmeng * @Date 2021-08-19 15:47 * * 描述: 过滤 HTML 标签中 XSS 代码 */public class JsoupUtil {/** * 使用自带的 basicWithImages 白名单* 允许的便签有 a,b,blockquote,br,cite,code,dd,dl,dt,em,i,li,ol,p,pre,q,small,span,strike,strong,sub,sup,u,ul,img* 以及 a 标签的 href,img 标签的 src,align,alt,height,width,title 属性*/private static final Whitelist whitelist = Whitelist.basicWithImages(); /** 配置过滤化参数, 不对代码进行格式化 */private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false); static {// 富文本编辑时一些样式是使用 style 来进行实现的// 比如红色字体 style="color:red; "// 所以需要给所有标签添加 style 属性whitelist.addAttributes(":all", "style"); }public static String clean(String content) {return Jsoup.clean(content, "", whitelist, outputSettings); }}
首先是定义参数过滤器:ParamsFilter 实现 Filter 类
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * Description : 参数过滤器 * */public class ParamsFilter implements Filter {@Overridepublic void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException {ParameterRequestWrapper parmsRequest = new ParameterRequestWrapper((HttpServletRequest) arg0); arg2.doFilter(parmsRequest, arg1); }@Overridepublic void init(FilterConfig arg0) throws ServletException {}@Overridepublic void destroy() {}}
添加参数过滤配置文件:
import gc.cnnvd.framework.core.filter.ParamsFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.DispatcherType; @Configurationpublic class ParameterTrimConfig {/*** 去除参数头尾空格过滤器* @return*/@Beanpublic FilterRegistrationBean parmsFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setDispatcherTypes(DispatcherType.REQUEST); registration.setFilter(new ParamsFilter()); registration.addUrlPatterns("/*"); registration.setName("paramsFilter"); registration.setOrder(Integer.MAX_VALUE-1); return registration; }}
处理都交给了这货:
import com.alibaba.fastjson.JSON; import gc.cnnvd.framework.config.converter.JsonValueTrimUtil; import gc.cnnvd.framework.util.JsoupUtil; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * * @Auther linmengmeng * @Date 2021-03-25 15:47 * * Description : 请求参数的处理, *1. 去除参数前后空格 *2. 过滤XSS非法字符 * */public class ParameterRequestWrapper extends HttpServletRequestWrapper {private Map params = new HashMap<>(); public ParameterRequestWrapper(HttpServletRequest request) {// 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似super(request); //将参数表,赋予给当前的Map以便于持有request中的参数Map requestMap=request.getParameterMap(); this.params.putAll(requestMap); this.modifyParameterValues(); }/*** 重写getInputStream方法post类型的请求参数必须通过流才能获取到值*/@Overridepublic ServletInputStream getInputStream() throws IOException {//非json类型,直接返回if (!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){return super.getInputStream(); }//为空,直接返回String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8); if (StringUtils.isEmpty(json)) {return super.getInputStream(); }Object resultObject = JsonValueTrimUtil.jsonStrTrim(json); //这里处理的是json传参的参数ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(resultObject).getBytes(StandardCharsets.UTF_8)); return new CustomServletInputStream(bis); }/*** 将parameter的值去除空格后重写回去*/public void modifyParameterValues(){Set set = params.keySet(); Iterator it = set.iterator(); while(it.hasNext()){String key = it.next(); String[] values = params.get(key); values[0] = values[0].trim(); values[0] = JsoupUtil.clean(values[0]); //这里处理的是form传参的参数params.put(key, values); }}/*** 重写getParameter 参数从当前类中的map获取*/@Overridepublic String getParameter(String name) {String[]values = params.get(name); if(values == null || values.length == 0) {return null; }return values[0]; }/*** 重写getParameterValues*/@Overridepublic String[] getParameterValues(String name) {//同上return params.get(name); }class CustomServletInputStream extendsServletInputStream{private ByteArrayInputStream bis; public CustomServletInputStream(ByteArrayInputStream bis){this.bis=bis; }@Overridepublic boolean isFinished() {return true; }@Overridepublic boolean isReady() {return true; }@Overridepublic void setReadListener(ReadListener listener) {}@Overridepublic int read() throws IOException {return bis.read(); }}}
上面form传的参数直接处理了,那么要是JSON传的参数,就要借助下面的工具类了:
import cn.hutool.json.JSONTokener; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import gc.cnnvd.framework.util.JsoupUtil; import org.apache.commons.lang3.StringUtils; import java.util.Map; import java.util.Set; /** * @Auther linmengmeng * @Date 2021-03-25 15:47 * 1. 去除Json字符串中的属性值前后空格的工具类 * 2. 去除 XSS 攻击字符 */public class JsonValueTrimUtil {public static Object jsonStrTrim(String jsonStr){if (StringUtils.isBlank(jsonStr)){return ""; }Object typeObject = new JSONTokener(jsonStr).nextValue(); if (typeObject instanceof cn.hutool.json.JSONObject){return jsonObjectTrim(JSONObject.parseObject(jsonStr)); }if (typeObject instanceof cn.hutool.json.JSONArray){return jsonArrayTrim(JSONArray.parseArray(jsonStr)); }jsonStr = JsoupUtil.clean(jsonStr); return jsonStr.trim(); }/*** @Description: 传入jsonObject 去除当中的空格* @param jsonObject* @return*/public static JSONObject jsonObjectTrim(JSONObject jsonObject){// 取出 jsonObject 中的字段的值的空格SetentrySets = jsonObject.entrySet(); entrySets.forEach(entry -> {Object value = https://www.it610.com/article/entry.getValue(); if (value == null){return; }if (value instanceof String) {String resultValue = (String) value; if (StringUtils.isNotBlank(resultValue)){resultValue = resultValue.trim(); resultValue = JsoupUtil.clean(resultValue); jsonObject.put(entry.getKey(), resultValue); }return; }if (value instanceof JSONObject){jsonObject.put(entry.getKey(), jsonObjectTrim((JSONObject) value)); return; }if (value instanceof JSONArray){jsonObject.put(entry.getKey(), jsonArrayTrim((JSONArray) value)); return; }}); return jsonObject; }/*** @Description: 将 jsonarry 的jsonObject 中的value值去处前后空格* @param arr* @return*/public static JSONArray jsonArrayTrim(JSONArray arr){if( arr != null && arr.size()> 0){Object tempObject = null; for (int i = 0; i < arr.size(); i++) {tempObject = arr.get(i); if (tempObject instanceof String){arr.set(i,tempObject ); continue; }JSONObject jsonObject = (JSONObject) arr.get(i); // 取出 jsonObject 中的字段的值的空格jsonObject = jsonObjectTrim(jsonObject); arr.set(i,jsonObject ); }}return arr; }}
测试一下:
import gc.cnnvd.framework.common.api.ApiResult; import gc.cnnvd.framework.log.annotation.OperationLogIgnore; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiOperation; import lombok.Data; import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.constraints.NotBlank; import java.io.Serializable; /** * @Auther linmengmeng * @Date 2021-03-30 16:24 */@Slf4j@RestController@RequestMapping("/tourist")@Api(value = "https://www.it610.com/article/测试游客页面xss", tags = {"游客页面xss"})public class TouristTestXssController {@PostMapping("/testXssForm")@OperationLogIgnore@ApiOperation(value = "https://www.it610.com/article/测试放开游客页面接口xssForm", notes = "测试放开游客页面接口xssForm", response = String.class)public ApiResult testXss(TestXssFormParam testXssFormParam) {log.info("form param testStr:[{}]", testXssFormParam.getTestStr()); // from 不好使return ApiResult.ok(testXssFormParam.getTestStr()); }@PostMapping("/testXssJson")@OperationLogIgnore@ApiOperation(value = "https://www.it610.com/article/测试放开游客页面接口xssJson", notes = "测试放开游客页面接口xssJson", response = String.class)public ApiResult testXssJson(@Validated @RequestBody TestXssFormParam testXssFormParam) {log.info("json param testStr:[{}]", testXssFormParam.getTestStr()); return ApiResult.ok(testXssFormParam.getTestStr()); }@Data@Accessors(chain = true)@ApiModel(value = "https://www.it610.com/article/testXss参数")public static class TestXssFormParam implements Serializable {private static final long serialVersionUID = 1L; @NotBlank(message = "testStr不能为空")@ApiModelProperty("testStr")private String testStr; }}
【SpringBoot去除参数前后空格和XSS过滤】上面接口里面的ApiResult为自定义封装的返回数据格式,可以直接修改接口返回类型改为String,就是为了看下后台处理后,返回前台是什么样的。
form传参,过滤成功。
文章图片
JSON传参,也没毛病。
文章图片
到此这篇关于SpringBoot去除参数前后空格和XSS过滤的文章就介绍到这了,更多相关SpringBoot去除参数前后空格和XSS过滤内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- Activiti(一)SpringBoot2集成Activiti6
- SpringBoot调用公共模块的自定义注解失效的解决
- 解决SpringBoot引用别的模块无法注入的问题
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- 接口|axios接口报错-参数类型错误解决
- springboot使用redis缓存
- performSelectorOnMainThread:withObject:waitUntilDone:参数设置为NO或YES的区别
- springboot整合数据库连接池-->druid
- iview|iview upload 动态改变上传参数
- SpringBoot中YAML语法及几个注意点说明