commit e7279d70b21bb2c612845f4d1305c0b42e6b9d7f Author: pioneer Date: Thu Jul 14 11:48:47 2022 +0800 open diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe02fd7 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# open-JSD-9719 + +JSD-9719 包括但不限于下拉框、下拉复选框、下拉树、单选按钮组、复选按钮组、视图树等控件会出现XSS注入问题,此插件用于对控件输入进行特殊字符过滤\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 \ No newline at end of file diff --git a/doc/JSD-9719-需求确认书V1.docx b/doc/JSD-9719-需求确认书V1.docx new file mode 100644 index 0000000..cf7cd4e Binary files /dev/null and b/doc/JSD-9719-需求确认书V1.docx differ diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..c81478e --- /dev/null +++ b/plugin.xml @@ -0,0 +1,16 @@ + + com.fr.plugin.safe.filter + + yes + 1.0.1 + 10.0 + 2020-07-31 + fr.open + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/SafedConfig.java b/src/main/java/com/fr/plugin/SafedConfig.java new file mode 100644 index 0000000..86a521e --- /dev/null +++ b/src/main/java/com/fr/plugin/SafedConfig.java @@ -0,0 +1,37 @@ +package com.fr.plugin; + +import com.fr.config.*; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; + +@Visualization(category = "安全过滤插件配置") +public class SafedConfig extends DefaultConfiguration { + + private static volatile SafedConfig config = null; + + public static SafedConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(SafedConfig.class); + } + return config; + } + + @Identifier(value = "openFlag", name = "开关", description = "开关", status = Status.SHOW) + private Conf openFlag = Holders.simple(true); + + public Boolean getOpenFlag() { + return openFlag.get(); + } + + public void setOpenFlag(Boolean openFlag) { + this.openFlag.set(openFlag); + } + + @Override + public Object clone() throws CloneNotSupportedException { + SafedConfig cloned = (SafedConfig) super.clone(); + cloned.openFlag = (Conf) openFlag.clone(); + return cloned; + } + +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/SafedFilter.java b/src/main/java/com/fr/plugin/SafedFilter.java new file mode 100644 index 0000000..08b5813 --- /dev/null +++ b/src/main/java/com/fr/plugin/SafedFilter.java @@ -0,0 +1,71 @@ +package com.fr.plugin; + +import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.transform.ExecuteFunctionRecord; +import com.fr.plugin.transform.FunctionRecorder; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +@FunctionRecorder(localeKey = "ffff") +public class SafedFilter extends AbstractGlobalRequestFilterProvider { + @Override + public String filterName() { + return "hfLogin"; + } + + @Override + public String[] urlPatterns() { + return new String[]{ + "/*" + }; + } + + @Override + public void init(FilterConfig filterConfig) { + SafedConfig.getInstance(); + FineLoggerFactory.getLogger().info("安全过滤支持插件初始化"); + super.init(filterConfig); + } + + @Override + @ExecuteFunctionRecord + public void doFilter(HttpServletRequest request, HttpServletResponse httpServletResponse, FilterChain filterChain) { + try { + if (SafedConfig.getInstance().getOpenFlag()) { + if (!isMultipartContent(request)) { + filterChain.doFilter(new XssFilterWrapper(request), httpServletResponse); + return; + } + } + filterChain.doFilter(request, httpServletResponse); + } catch (IOException | ServletException e) { + printException2FrLog(e); + } catch (Exception e) { + printException2FrLog(e); + } + } + + private boolean isMultipartContent(HttpServletRequest request) { + if (!"post".equalsIgnoreCase(request.getMethod())) { + return false; + } + String contentType = request.getContentType(); //获取Content-Type + return (contentType != null) && (contentType.toLowerCase().startsWith("multipart/")); + } + + public static void printException2FrLog(Throwable e) { + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + String s = writer.toString(); + FineLoggerFactory.getLogger().error("错误:{}", s); + } + +} diff --git a/src/main/java/com/fr/plugin/XssFilterWrapper.java b/src/main/java/com/fr/plugin/XssFilterWrapper.java new file mode 100644 index 0000000..8274b01 --- /dev/null +++ b/src/main/java/com/fr/plugin/XssFilterWrapper.java @@ -0,0 +1,38 @@ +package com.fr.plugin; + +import com.fr.stable.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +public class XssFilterWrapper extends HttpServletRequestWrapper { + public XssFilterWrapper(HttpServletRequest request) { + super(request); + } + + @Override + public String getParameter(String name) { + String parameter = super.getParameter(name); + return StringUtils.isNotBlank(parameter) ? htmlEscape(parameter) : parameter; + } + + private String htmlEscape(String str) { + return str.replaceAll("<", "<").replaceAll(">", ">"); + } + + /** + * 对数组参数进行特殊字符过滤 + */ + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values == null) { + return null; + } + String[] newValues = new String[values.length]; + for (int i = 0; i < values.length; i++) { + newValues[i] = htmlEscape(values[i]);//spring的HtmlUtils进行转义 + } + return newValues; + } +} \ No newline at end of file