diff --git a/ThunderSoft_repeatsubmitfilter/README.md b/ThunderSoft_repeatsubmitfilter/README.md
new file mode 100644
index 000000000..f81e306dc
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/README.md
@@ -0,0 +1,19 @@
+# ShortUrl
+Repeatsubmitfilter是一个防止重复提交的依赖库
+
+
+## 逻辑详情
+系统加载直接自动使用
+
+## 使用步骤说明
+
+1. 应用引用依赖库
+2. 配置应用配置参数 (无需配置)
+3. 逻辑调用示例截图
+注意:需要根据自己的业务修改一下放行的白名单
+
+参考文档
+
+## 应用演示链接
+
+[使用了本依赖库的制品应用链接]
diff --git a/ThunderSoft_repeatsubmitfilter/lib/nasl-metadata-collector-0.7.0.jar b/ThunderSoft_repeatsubmitfilter/lib/nasl-metadata-collector-0.7.0.jar
new file mode 100644
index 000000000..f085868b0
Binary files /dev/null and b/ThunderSoft_repeatsubmitfilter/lib/nasl-metadata-collector-0.7.0.jar differ
diff --git a/ThunderSoft_repeatsubmitfilter/pom.xml b/ThunderSoft_repeatsubmitfilter/pom.xml
new file mode 100644
index 000000000..56982ed4e
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/pom.xml
@@ -0,0 +1,81 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.9.RELEASE
+
+
+ com.hq
+ repeatsubmitfilter
+ 1.1.6
+ 弱网情况下防止重复提交
+
+ 8
+ 8
+ UTF-8
+ 3.3
+
+
+
+
+ nasl-metadata-collector
+ com.netease.lowcode
+ 0.7.0
+ true
+ system
+ ${project.basedir}/lib/nasl-metadata-collector-0.7.0.jar
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.3.0
+
+
+ jar-with-dependencies
+
+ false
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+ com.netease.lowcode
+ nasl-metadata-maven-plugin
+ 1.3.0
+
+ true
+
+
+
+
+ archive
+
+
+
+
+
+
+
diff --git "a/ThunderSoft_repeatsubmitfilter/repeatsubmitfilter\344\276\235\350\265\226\345\214\205.docx" "b/ThunderSoft_repeatsubmitfilter/repeatsubmitfilter\344\276\235\350\265\226\345\214\205.docx"
new file mode 100644
index 000000000..36a34f211
Binary files /dev/null and "b/ThunderSoft_repeatsubmitfilter/repeatsubmitfilter\344\276\235\350\265\226\345\214\205.docx" differ
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/java/com/cache/Cache.java b/ThunderSoft_repeatsubmitfilter/src/main/java/com/cache/Cache.java
new file mode 100644
index 000000000..626886d7e
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/java/com/cache/Cache.java
@@ -0,0 +1,51 @@
+package com.cache;
+
+
+public class Cache {
+ private String key;//缓存ID
+ private Object value;//缓存数据
+ private long timeOut;//更新时间
+ private boolean expired; //是否终止
+ public Cache() {
+ super();
+ }
+
+ public Cache(String key, Object value, long timeOut, boolean expired) {
+ this.key = key;
+ this.value = value;
+ this.timeOut = timeOut;
+ this.expired = expired;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public long getTimeOut() {
+ return timeOut;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setKey(String string) {
+ key = string;
+ }
+
+ public void setTimeOut(long l) {
+ timeOut = l;
+ }
+
+ public void setValue(Object object) {
+ value = object;
+ }
+
+ public boolean isExpired() {
+ return expired;
+ }
+
+ public void setExpired(boolean b) {
+ expired = b;
+ }
+}
\ No newline at end of file
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/java/com/cache/CacheManager.java b/ThunderSoft_repeatsubmitfilter/src/main/java/com/cache/CacheManager.java
new file mode 100644
index 000000000..6a548e0f8
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/java/com/cache/CacheManager.java
@@ -0,0 +1,198 @@
+package com.cache;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+
+public class CacheManager {
+ private static HashMap cacheMap = new HashMap();
+
+ //单实例构造方法
+ private CacheManager() {
+ super();
+ }
+ //获取布尔值的缓存
+ public static boolean getSimpleFlag(String key){
+ try{
+ return (Boolean) cacheMap.get(key);
+ }catch(NullPointerException e){
+ return false;
+ }
+ }
+ public static long getServerStartdt(String key){
+ try {
+ return (Long)cacheMap.get(key);
+ } catch (Exception ex) {
+ return 0;
+ }
+ }
+ //设置布尔值的缓存
+ public static boolean setSimpleFlag(String key,boolean flag){
+ if (flag && getSimpleFlag(key)) {//假如为真不允许被覆盖
+ return false;
+ }else{
+ cacheMap.put(key, flag);
+ return true;
+ }
+ }
+ public static boolean setSimpleFlag(String key,long serverbegrundt){
+ if (cacheMap.get(key) == null) {
+ cacheMap.put(key,serverbegrundt);
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+
+ //得到缓存。同步静态方法
+ private synchronized static Cache getCache(String key) {
+ return (Cache) cacheMap.get(key);
+ }
+
+ //判断是否存在一个缓存
+ private synchronized static boolean hasCache(String key) {
+ return cacheMap.containsKey(key);
+ }
+
+ //清除所有缓存
+ public synchronized static void clearAll() {
+ cacheMap.clear();
+ }
+
+ //清除某一类特定缓存,通过遍历HASHMAP下的所有对象,来判断它的KEY与传入的TYPE是否匹配
+ public synchronized static void clearAll(String type) {
+ Iterator i = cacheMap.entrySet().iterator();
+ String key;
+ ArrayList arr = new ArrayList();
+ try {
+ while (i.hasNext()) {
+ java.util.Map.Entry entry = (java.util.Map.Entry) i.next();
+ key = (String) entry.getKey();
+ if (key.startsWith(type)) { //如果匹配则删除掉
+ arr.add(key);
+ }
+ }
+ for (int k = 0; k < arr.size(); k++) {
+ clearOnly(arr.get(k));
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ //清除指定的缓存
+ public synchronized static void clearOnly(String key) {
+ cacheMap.remove(key);
+ }
+
+ //载入缓存
+ public synchronized static void putCache(String key, Cache obj) {
+ cacheMap.put(key, obj);
+ }
+
+ //获取缓存信息
+ public static Cache getCacheInfo(String key) {
+
+ if (hasCache(key)) {
+ Cache cache = getCache(key);
+ if (cacheExpired(cache)) { //调用判断是否终止方法
+ cache.setExpired(true);
+ }
+ return cache;
+ }else
+ return null;
+ }
+
+ //载入缓存信息
+ public static void putCacheInfo(String key, Cache obj, long dt, boolean expired) {
+ Cache cache = new Cache();
+ cache.setKey(key);
+ cache.setTimeOut(dt + System.currentTimeMillis()); //设置多久后更新缓存
+ cache.setValue(obj);
+ cache.setExpired(expired); //缓存默认载入时,终止状态为FALSE
+ cacheMap.put(key, cache);
+ }
+ //重写载入缓存信息方法
+ public static void putCacheInfo(String key, Cache obj, long dt){
+ Cache cache = new Cache();
+ cache.setKey(key);
+ cache.setTimeOut(dt+System.currentTimeMillis());
+ cache.setValue(obj);
+ cache.setExpired(false);
+ cacheMap.put(key,cache);
+ }
+
+ //判断缓存是否终止
+ public static boolean cacheExpired(Cache cache) {
+ if (null == cache) { //传入的缓存不存在
+ return false;
+ }
+ long nowDt = System.currentTimeMillis(); //系统当前的毫秒数
+ long cacheDt = cache.getTimeOut(); //缓存内的过期毫秒数
+ if (cacheDt <= 0||cacheDt>nowDt) { //过期时间小于等于零时,或者过期时间大于当前时间时,则为FALSE
+ return false;
+ } else { //大于过期时间 即过期
+ return true;
+ }
+ }
+
+ //获取缓存中的大小
+ public static int getCacheSize() {
+ return cacheMap.size();
+ }
+
+ //获取指定的类型的大小
+ public static int getCacheSize(String type) {
+ int k = 0;
+ Iterator i = cacheMap.entrySet().iterator();
+ String key;
+ try {
+ while (i.hasNext()) {
+ java.util.Map.Entry entry = (java.util.Map.Entry) i.next();
+ key = (String) entry.getKey();
+ if (key.indexOf(type) != -1) { //如果匹配则删除掉
+ k++;
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ return k;
+ }
+
+ //获取缓存对象中的所有键值名称
+ public static ArrayList getCacheAllkey() {
+ ArrayList a = new ArrayList();
+ try {
+ Iterator i = cacheMap.entrySet().iterator();
+ while (i.hasNext()) {
+ java.util.Map.Entry entry = (java.util.Map.Entry) i.next();
+ a.add((String) entry.getKey());
+ }
+ } catch (Exception ex) {} finally {
+ return a;
+ }
+ }
+
+ //获取缓存对象中指定类型 的键值名称
+ public static ArrayList getCacheListkey(String type) {
+ ArrayList a = new ArrayList();
+ String key;
+ try {
+ Iterator i = cacheMap.entrySet().iterator();
+ while (i.hasNext()) {
+ java.util.Map.Entry entry = (java.util.Map.Entry) i.next();
+ key = (String) entry.getKey();
+ if (key.indexOf(type) != -1) {
+ a.add(key);
+ }
+ }
+ } catch (Exception ex) {} finally {
+ return a;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/LibhqFilterEnvironmentConfiguration.java b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/LibhqFilterEnvironmentConfiguration.java
new file mode 100644
index 000000000..830c2e292
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/LibhqFilterEnvironmentConfiguration.java
@@ -0,0 +1,15 @@
+package com.hq;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 加入spring环境配置(在spring.factories中指定)
+ */
+@Configuration
+@ComponentScan(basePackageClasses = LibraryAutoScan.class)
+public class LibhqFilterEnvironmentConfiguration {
+ public LibhqFilterEnvironmentConfiguration() {
+ System.out.println("LibhqFilterEnvironmentConfiguration");
+ }
+}
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/LibraryAutoScan.java b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/LibraryAutoScan.java
new file mode 100644
index 000000000..8269e7526
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/LibraryAutoScan.java
@@ -0,0 +1,8 @@
+package com.hq;
+
+/**
+ * 依赖库自动扫描类
+ * @author system
+ */
+public class LibraryAutoScan {
+}
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/RequestWrapper.java b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/RequestWrapper.java
new file mode 100644
index 000000000..5625b4101
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/RequestWrapper.java
@@ -0,0 +1,63 @@
+package com.hq.filter;
+
+import org.springframework.util.StreamUtils;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+public class RequestWrapper extends HttpServletRequestWrapper {
+ private final byte[] body;
+
+ public RequestWrapper(HttpServletRequest request) throws IOException {
+ super(request);
+ //保存一份InputStream,将其转换为字节数组
+ body = StreamUtils.copyToByteArray(request.getInputStream());
+ }
+
+ //转换成String
+ public String getBodyString(){
+ return new String(body, StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+ //把保存好的InputStream,传下去
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+
+ final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+
+ return new ServletInputStream() {
+
+ @Override
+ public int read() throws IOException {
+ return bais.read();
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ }
+ };
+ }
+}
+
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/RestartSubmitFilter.java b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/RestartSubmitFilter.java
new file mode 100644
index 000000000..561a2bb6f
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/RestartSubmitFilter.java
@@ -0,0 +1,103 @@
+package com.hq.filter;
+
+import com.cache.CacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.*;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+
+@Component
+public class RestartSubmitFilter implements Filter {
+
+ public static final String LOGIC_IDENTIFIER_SEPARATOR = ":";
+ private Logger logger = LoggerFactory.getLogger(RestartSubmitFilter.class);
+
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ String requestURI = request.getRequestURI();
+ logger.warn("requestURI========" + requestURI);
+ if (!StringUtils.isEmpty(requestURI) && requestURI.contains("/management") || requestURI.contains("/api/lcplogics/LoginUser")
+ || requestURI.contains("/upload/")||requestURI.contains("/system/getUser")
+ ||requestURI.contains("/nuims/nuims")||requestURI.contains("/system/config")||requestURI.contains("/m/login")||requestURI.contains("/m")
+ ||requestURI.contains("api/lcplogics/")) {
+ filterChain.doFilter(servletRequest, servletResponse);
+ return;
+ }
+ requestURI = request.getRemoteHost() + request.getRequestURI();
+ Cookie[] cookies = request.getCookies();
+ String value = null;
+ logger.warn("cookies========" + cookies.toString());
+ for (Cookie cookie : cookies) {
+ String name = cookie.getName();
+ if ("authorization".equals(name)) {
+ value = cookie.getValue();
+ break;
+ }
+ }
+ logger.warn("authorization========" + value);
+ String method = request.getMethod();
+ logger.warn("method========" + method);
+ RequestWrapper requestWrapper = new RequestWrapper(request);
+ String bodyString = requestWrapper.getBodyString();
+ logger.warn("bodyString========" + bodyString);
+ String logicIdentifier = requestURI + LOGIC_IDENTIFIER_SEPARATOR + method + LOGIC_IDENTIFIER_SEPARATOR + value + LOGIC_IDENTIFIER_SEPARATOR + bodyString;
+ boolean bool = CacheManager.setSimpleFlag(logicIdentifier, 1);
+ if (bool) {
+ logger.info("filter in");
+ filterChain.doFilter(requestWrapper, servletResponse);
+ CacheManager.clearOnly(logicIdentifier);
+ logger.info("filter out");
+ return;
+ }
+ logger.warn("filter ===============Repeated submission intercepted");
+ }
+
+ //获取Request的body数据
+ private String getBody(ServletRequest request) {
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = null;
+ InputStream inputStream = null;
+ try {
+ inputStream = request.getInputStream();
+ if (inputStream != null) {
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ char[] charBuffer = new char[128];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ } else {
+ stringBuilder.append("");
+ }
+ } catch (IOException ex) {
+
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (bufferedReader != null) {
+ try {
+ bufferedReader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return stringBuilder.toString();
+ }
+}
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/Temp.java b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/Temp.java
new file mode 100644
index 000000000..a8282b8b8
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/java/com/hq/filter/Temp.java
@@ -0,0 +1,10 @@
+package com.hq.filter;
+
+import com.netease.lowcode.core.annotation.NaslStructure;
+
+/**
+ * 由于打包必须有nasl标签,所以创建临时类。若项目中有nasl标签的类,则不需要此类。
+ */
+@NaslStructure
+public class Temp {
+}
diff --git a/ThunderSoft_repeatsubmitfilter/src/main/resources/META-INF/spring.factories b/ThunderSoft_repeatsubmitfilter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..371e1dda6
--- /dev/null
+++ b/ThunderSoft_repeatsubmitfilter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.hq.LibhqFilterEnvironmentConfiguration
\ No newline at end of file