seyason 4 سال پیش
والد
کامیت
8bb069dd56

+ 78 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/aop/SensitiveWordConfig.java

@@ -0,0 +1,78 @@
+package com.management.platform.aop;
+
+import com.management.platform.util.RedisUtil;
+import com.management.platform.util.WordFilter;
+import lombok.SneakyThrows;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * 敏感词过滤
+ */
+@Aspect
+@Component
+public class SensitiveWordConfig {
+    @Autowired
+    RedisUtil redisUtils;
+    @Autowired
+    WordFilter wordFilter;
+    @Around("@annotation(org.springframework.web.bind.annotation.PostMapping)||@annotation(org.springframework.web.bind.annotation.PutMapping)")
+    @SneakyThrows
+    public Object doBefore(ProceedingJoinPoint point) {
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        if (request.getRequestURI().contains("/word/sensitiveword")) {
+            return point.proceed();
+        }
+        //所有的参数对象
+        for (Object arg : point.getArgs()) {
+            //参数对象,通过反射将String类型的值进行敏感词过滤
+            Class<?> aClass = arg.getClass();
+            //递归遍历,将所有String参数进行敏感词匹配
+            foundString(aClass,arg);
+        }
+        return  point.proceed();
+    }
+
+    /**
+     * @author: zhangyb
+     * @date:  2020/11/19 13:57
+     * @Description: 递归将String替换
+     * @UpdateUser : zhangyb
+     * @UpdateDate :2020/11/19 13:57
+     * @UpdateRemark:
+     */
+    @SneakyThrows
+    public Class<?> foundString(Class clazz,Object arg ){
+        Field[] declaredFields = clazz.getDeclaredFields();
+        for (Field declaredField : declaredFields) {
+            Class<?> type = declaredField.getType();
+            if (type==String.class&&!Modifier.toString(declaredField.getModifiers()).contains("final")){
+                //如果是String类型,进行关键词匹配 且要排除final修饰的字段
+                declaredField.setAccessible(true);
+                String value=(String)declaredField.get(arg);
+                declaredField.set(arg, wordFilter.replaceWords(value));
+            }else if (type.getPackage()!=null&&type.getPackage().getName().contains("com.bysk")){
+                Method[] methods = clazz.getMethods();
+                for (Method method : methods) {
+                    String name = method.getName();
+                    if (name.toLowerCase().contains("get"+declaredField.getName().toLowerCase())){
+                        Object invoke = method.invoke(arg);
+                        this.foundString(type,invoke);
+                        break;
+                    }
+                }
+            }
+        }
+        return  clazz;
+    }
+}

+ 56 - 15
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java

@@ -7,18 +7,20 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.Map;
+
 @RestController
 @RequestMapping("/")
 public class DingDingController {
-    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final Logger bizLogger = LoggerFactory.getLogger(getClass());
     String token = "cf776d62c5fb3508b5d8c2cbb9f3df0c";
     String aesKey = "ktmbamhymjsf60ndwp6n81mnu92847oynsgj9e0zr9v";
-    String corpId = "169917db7f1ee5f435c2f4657eb6378f";
+    String suiteKey = "suitejwoq9dw4bxv4stdb";
 
     @PostMapping(value = "dingCallback")
-    public Object dingCallback(
+    public Map<String, String> dingCallback(
             @RequestParam(value = "signature") String signature,
-            @RequestParam(value = "timestamp") Long timestamp,
+            @RequestParam(value = "timestamp") String timestamp,
             @RequestParam(value = "nonce") String nonce,
             @RequestBody(required = false) JSONObject body
     ) {
@@ -35,21 +37,60 @@ public class DingDingController {
 //        String eventType = callBackContent.getString("EventType");
         //TODO 将数据持久化
 //        return plainText;
+//        try {
+//            DingCallbackCrypto encryptor = new DingCallbackCrypto(token, aesKey, suiteKey);
+//            String encrypt = body.getString("encrypt");
+//            String plainText = encryptor.getDecryptMsg(signature, timestamp.toString(), nonce, encrypt);
+//            JSONObject callBackContent = JSON.parseObject(plainText);
+//                    // 根据回调事件类型做不同的业务处理
+//            String eventType = callBackContent.getString("EventType");
+//            log.info("eventType=="+eventType);
+//            System.out.println("eventType=="+eventType);
+//            System.out.println("plainText=="+plainText);
+//
+//
+//            return plainText;
+//        } catch (DingCallbackCrypto.DingTalkEncryptException e) {
+//            e.printStackTrace();
+//            return e.getMessage();
+//        }
+
         try {
-            DingCallbackCrypto encryptor = new DingCallbackCrypto(token, aesKey, corpId);
-            String encrypt = body.getString("encrypt");
-            String plainText = encryptor.getDecryptMsg(signature, timestamp.toString(), nonce, encrypt);
-            JSONObject callBackContent = JSON.parseObject(plainText);
-                    // 根据回调事件类型做不同的业务处理
-            String eventType = callBackContent.getString("EventType");
-            log.info("eventType=="+eventType);
-            System.out.println("eventType=="+eventType);
-            System.out.println("plainText=="+plainText);
-            return plainText;
+            // 1. 从http请求中获取加解密参数
+
+            // 2. 使用加解密类型
+            // Constant.OWNER_KEY 说明:
+            // 1、开发者后台配置的订阅事件为应用级事件推送,
+            //      此时OWNER_KEY为应用的APP_KEY(企业内部应用)或SUITE_KEY(三方应用)。
+            // 2、调用订阅事件接口订阅的事件为企业级事件推送,
+            //      此时OWNER_KEY为:企业的CORP_ID(企业内部应用)或SUITE_KEY(三方应用)
+            DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(token, aesKey, suiteKey);
+            String encryptMsg = body.getString("encrypt");
+            String decryptMsg = callbackCrypto.getDecryptMsg(signature, timestamp, nonce, encryptMsg);
+
+            // 3. 反序列化回调事件json数据
+            JSONObject eventJson = JSON.parseObject(decryptMsg);
+            String eventType = eventJson.getString("EventType");
+
+            // 4. 根据EventType分类处理
+            if ("check_url".equals(eventType)) {
+                // 测试回调url的正确性
+                bizLogger.info("测试回调url的正确性");
+            } else if ("user_add_org".equals(eventType)) {
+                // 处理通讯录用户增加事件
+                bizLogger.info("发生了:" + eventType + "事件");
+            } else {
+                // 添加其他已注册的
+                bizLogger.info("发生了:" + eventType + "事件");
+            }
+
+            // 5. 返回success的加密数据
+            Map<String, String> successMap = callbackCrypto.getEncryptedMap("success");
+            return successMap;
         } catch (DingCallbackCrypto.DingTalkEncryptException e) {
             e.printStackTrace();
         }
-        return "fail";
+        return null;
     }
 
 }

+ 135 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WordFilter.java

@@ -0,0 +1,135 @@
+package com.management.platform.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+
+@Slf4j
+@Component
+public class WordFilter {
+    private final static String WORDS = "WORDS";
+    private final static String REPLACE_CHAR = "*";
+    private static HashMap sensitiveWordMap;
+    /**     * 最小匹配规则     */
+    private static int minMatchTYpe = 1;
+    /**     * 最大匹配规则     */
+    private static int maxMatchType = 2;
+//    @Autowired
+//    private RedisTemplate<String, Object> redisTemplate;
+//    @Autowired
+//    private SensitiveWordMapper sensitiveWordMapper ;
+//
+    public  String replaceWords(String text) {
+        if (StringUtils.isBlank(text)) {
+            return text;
+        }
+//        List<Object> words = redisTemplate.opsForList().range("SensitiveWord", 0, -1);
+//        if (words.size()<=0){
+//            words=sensitiveWordMapper.listStr();
+//            //更新redis
+//            redisTemplate.opsForList().leftPushAll("SensitiveWord",sensitiveWordMapper.listStr());
+//        }
+        //缓存获取敏感词汇原记录
+//        return WordFilter.replaceSensitiveWord(words, text, WordFilter.minMatchTYpe);
+        return null;
+    }
+
+    /**
+     * 替换敏感字字符
+     *
+     * @param data      敏感字集合
+     * @param txt       待检查文本
+     * @param matchType 匹配规则
+     */
+    private static String replaceSensitiveWord(List<Object> data, String txt, int matchType) {
+        if (sensitiveWordMap == null) {
+            addSensitiveWord(data);
+        }
+        String resultTxt = txt;
+        //获取所有的敏感词
+        List<String> set = getSensitiveWord(txt, matchType);
+        Iterator<String> iterator = set.iterator();
+        while (iterator.hasNext()) {
+            resultTxt = resultTxt.replaceAll(iterator.next(), REPLACE_CHAR);
+        }
+        return resultTxt;
+    }
+
+
+    /**
+     * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:
+     * 说明:该方法来源于互联网
+     */
+    private static void addSensitiveWord(List<Object> datas) {
+        sensitiveWordMap = new HashMap(datas.size());
+        Iterator<Object> iterator = datas.iterator();
+        Map<String, Object> now = null;
+        Map now2 = null;
+        while (iterator.hasNext()) {
+            now2 = sensitiveWordMap;
+            String word = (String)iterator.next(); //敏感词
+            word=word.trim();
+            for (int i = 0; i < word.length(); i++) {
+                char key_word = word.charAt(i);
+                Object obj = now2.get(key_word);
+                if (obj != null) { //存在
+                    now2 = (Map) obj;
+                } else { //不存在
+                    now = new HashMap<String, Object>();
+                    now.put("isEnd", "0");
+                    now2.put(key_word, now);
+                    now2 = now;
+                }
+                if (i == word.length() - 1) {
+                    now2.put("isEnd", "1");
+                }
+            }
+        }
+    }
+
+    /**
+     * 获取内容中的敏感词
+     *说明:该方法来源于互联网
+     * @param text      内容
+     * @param matchType 匹配规则 1=不最佳匹配,2=最佳匹配
+     * @return
+     */
+    private static List<String> getSensitiveWord(String text, int matchType) {
+        List<String> words = new ArrayList<String>();
+        Map now = sensitiveWordMap;
+        int count = 0; //初始化敏感词长度
+        int start = 0; //标志敏感词开始的下标
+        for (int i = 0; i < text.length(); i++) {
+            char key = text.charAt(i);
+            now = (Map) now.get(key);
+            if (now != null) { //存在
+                count++;
+                if (count == 1) {
+                    start = i;
+                }
+                if ("1".equals(now.get("isEnd"))) { //敏感词结束
+                    now = sensitiveWordMap; //重新获取敏感词库
+                    words.add(text.substring(start, start + count)); //取出敏感词,添加到集合
+                    count = 0; //初始化敏感词长度
+                }
+            } else { //不存在
+                now = sensitiveWordMap;//重新获取敏感词库
+                if (count == 1 && matchType == 1) { //不最佳匹配
+                    count = 0;
+                } else if (count == 1 && matchType == 2) { //最佳匹配
+                    words.add(text.substring(start, start + count));
+                    count = 0;
+                }
+            }
+        }
+        return words;
+    }
+    public WordFilter() {
+        super();
+    }
+
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4483 - 4425
fhKeeper/formulahousekeeper/timesheet_h5/package-lock.json


+ 19 - 20
fhKeeper/formulahousekeeper/timesheet_h5/package.json

@@ -11,34 +11,33 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
-    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
-    "babel-plugin-import": "^1.12.2",
-    "core-js": "^2.6.5",
-    "css-loader": "^3.2.0",
-    "echarts": "^4.2.1",
-    "style-loader": "^1.0.0",
-    "vant": "^2.5.2",
-    "vue": "^2.6.10",
-    "vuex-persistedstate": "^2.5.4"
+    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+    "babel-plugin-import": "^1.13.3",
+    "core-js": "^2.6.12",
+    "css-loader": "^3.6.0",
+    "echarts": "^4.9.0",
+    "style-loader": "^1.3.0",
+    "vue": "^2.6.12",
+    "vuex-persistedstate": "^2.7.1"
   },
   "devDependencies": {
-    "@vue/cli-plugin-babel": "^3.7.0",
-    "@vue/cli-plugin-eslint": "^3.7.0",
-    "@vue/cli-service": "^4.2.2",
+    "@vue/cli-plugin-babel": "^3.12.1",
+    "@vue/cli-plugin-eslint": "^3.12.1",
+    "@vue/cli-service": "^4.5.13",
     "amfe-flexible": "^2.2.1",
-    "autoprefixer": "^9.5.1",
+    "autoprefixer": "^9.8.6",
     "axios": "^0.18.1",
-    "babel-eslint": "^10.0.1",
+    "babel-eslint": "^10.1.0",
     "eslint": "^5.16.0",
-    "eslint-plugin-vue": "^5.0.0",
-    "less": "^3.9.0",
+    "eslint-plugin-vue": "^5.2.3",
+    "less": "^3.13.1",
     "less-loader": "^5.0.0",
     "postcss-loader": "^3.0.0",
     "postcss-pxtorem": "^4.0.1",
-    "vant": "^2.2.9",
-    "vue-router": "^3.0.6",
-    "vue-template-compiler": "^2.5.21",
-    "vuex": "^3.1.0"
+    "vant": "^2.12.18",
+    "vue-router": "^3.5.1",
+    "vue-template-compiler": "^2.6.12",
+    "vuex": "^3.6.2"
   },
   "eslintConfig": {
     "root": true,

+ 3 - 0
fhKeeper/formulahousekeeper/timesheet_h5/public/index.html

@@ -9,6 +9,9 @@
     <title>工时管家</title>
     <link rel="stylesheet" href="http://at.alicdn.com/t/font_1456778_1mgn5degp7t.css">
     <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
+
+    <meta name="wpk-bid" content="dta_2_71020"> <script>    !(function(c,i,e,b){var h=i.createElement("script");var f=i.getElementsByTagName("script")[0];h.type="text/javascript";h.crossorigin=true;h.onload=function(){c[b]||(c[b]=new c.wpkReporter({bid:"dta_2_71020"}));c[b].installAll()};f.parentNode.insertBefore(h,f);h.src=e})(window,document,"https://g.alicdn.com/woodpeckerx/jssdk??wpkReporter.js","__wpk");</script>
+    
 </head>
 
 <body>

BIN
fhKeeper/formulahousekeeper/timesheet_h5/src/assets/img/index/banner4.jpeg


+ 3 - 3
fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue

@@ -28,9 +28,9 @@
                 user: JSON.parse(localStorage.userInfo),
                 unreadNum:0,
                 images: [
-                    require('../../assets/img/index/banner_1.png'),
-                    require('../../assets/img/index/banner_2.png'),
-                    require('../../assets/img/index/banner_3.png'),
+                    // require('../../assets/img/index/banner_1.png'),
+                    require('../../assets/img/index/banner4.jpeg'),
+                    // require('../../assets/img/index/banner_3.png'),
                 ],
                 routers: [
                     {