commit
e7279d70b2
6 changed files with 168 additions and 0 deletions
@ -0,0 +1,6 @@
|
||||
# open-JSD-9719 |
||||
|
||||
JSD-9719 包括但不限于下拉框、下拉复选框、下拉树、单选按钮组、复选按钮组、视图树等控件会出现XSS注入问题,此插件用于对控件输入进行特殊字符过滤\ |
||||
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 |
Binary file not shown.
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><plugin> |
||||
<id>com.fr.plugin.safe.filter</id> |
||||
<name><![CDATA[安全过滤支持插件]]></name> |
||||
<active>yes</active> |
||||
<version>1.0.1</version> |
||||
<env-version>10.0</env-version> |
||||
<jartime>2020-07-31</jartime> |
||||
<vendor>fr.open</vendor> |
||||
<description><![CDATA[安全过滤支持插件]]></description> |
||||
<change-notes><![CDATA[ |
||||
]]></change-notes> |
||||
<extra-decision> |
||||
<GlobalRequestFilterProvider class="com.fr.plugin.SafedFilter"/> |
||||
</extra-decision> |
||||
<function-recorder class="com.fr.plugin.SafedFilter"/> |
||||
</plugin> |
@ -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<Boolean> 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<Boolean>) openFlag.clone(); |
||||
return cloned; |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
Loading…
Reference in new issue