Sfoglia il codice sorgente

1.修复富文本过滤敏感词问题

jasonk5949 4 mesi fa
parent
commit
9f1cfd1ae4

+ 5 - 0
snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/pom.xml

@@ -47,5 +47,10 @@
             <groupId>vip.xiaonuo</groupId>
             <artifactId>snowy-plugin-disk-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.jsoup</groupId>
+            <artifactId>jsoup</artifactId>
+            <version>1.16.1</version>
+        </dependency>
     </dependencies>
 </project>

+ 96 - 19
snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/service/impl/ForumPostInfoServiceImpl.java

@@ -22,6 +22,12 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.nodes.TextNode;
+import org.jsoup.select.NodeTraversor;
+import org.jsoup.select.NodeVisitor;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -59,13 +65,14 @@ import vip.xiaonuo.sys.api.SysUserApi;
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -202,7 +209,9 @@ public class ForumPostInfoServiceImpl extends ServiceImpl<ForumPostInfoMapper, F
             forumPostInfo.setUserId(loginUser.getId());
             // 过滤敏感词(标题)
             String titleIsIllegal = filterSensitiveWordsTitle(forumPostInfoAddParam.getPostTitle());
-            if("1".equals(titleIsIllegal))return CommonResult.error("帖子标题含有敏感词");
+            if("1".equals(titleIsIllegal)) {
+                return CommonResult.error("帖子标题含有敏感词");
+            }
             // 过滤敏感词(内容)
             String postContent = filterSensitiveWords(forumPostInfoAddParam.getPostContent(), loginUser, uuid);
             forumPostInfo.setPostContent(postContent);
@@ -260,26 +269,92 @@ public class ForumPostInfoServiceImpl extends ServiceImpl<ForumPostInfoMapper, F
      *
      * @param postContent 帖子内容
      */
+//    public String filterSensitiveWords(String postContent, SaBaseLoginUser loginUser, String uuid) {
+//        List<ForumSensitivity> forumSensitivities = forumSensitivityMapper.selectList(new QueryWrapper<>());
+//        if (forumSensitivities.size() > 0) {
+//            // 过滤敏感词
+//            for (ForumSensitivity forumSensitivity : forumSensitivities) {
+//                // 过滤逻辑
+//                if (postContent.contains(forumSensitivity.getSensitivityWord())) {
+//                    // 替换句子中敏感词为*号
+//                    postContent = postContent.replace(forumSensitivity.getSensitivityWord(), "******");
+//                    // 记录敏感词命中情况
+//                    ForumSensitivityRecord forumSensitivityRecord = new ForumSensitivityRecord();
+//                    forumSensitivityRecord.setSensitivityWord(forumSensitivity.getSensitivityWord()); // 敏感词
+//                    forumSensitivityRecord.setUserId(loginUser.getId()); // 用户id
+//                    forumSensitivityRecord.setRecordType(0); // 发帖子类型
+//                    forumSensitivityRecord.setPostId(uuid); // 帖子id
+//                    forumSensitivityRecordMapper.insert(forumSensitivityRecord);
+//                }
+//            }
+//        }
+//        return postContent;
+//    }
+
     public String filterSensitiveWords(String postContent, SaBaseLoginUser loginUser, String uuid) {
+        // 查询敏感词列表
         List<ForumSensitivity> forumSensitivities = forumSensitivityMapper.selectList(new QueryWrapper<>());
-        if (forumSensitivities.size() > 0) {
-            // 过滤敏感词
-            for (ForumSensitivity forumSensitivity : forumSensitivities) {
-                // 过滤逻辑
-                if (postContent.contains(forumSensitivity.getSensitivityWord())) {
-                    // 替换句子中敏感词为*号
-                    postContent = postContent.replace(forumSensitivity.getSensitivityWord(), "******");
-                    // 记录敏感词命中情况
-                    ForumSensitivityRecord forumSensitivityRecord = new ForumSensitivityRecord();
-                    forumSensitivityRecord.setSensitivityWord(forumSensitivity.getSensitivityWord()); // 敏感词
-                    forumSensitivityRecord.setUserId(loginUser.getId()); // 用户id
-                    forumSensitivityRecord.setRecordType(0); // 发帖子类型
-                    forumSensitivityRecord.setPostId(uuid); // 帖子id
-                    forumSensitivityRecordMapper.insert(forumSensitivityRecord);
+        if (forumSensitivities == null || forumSensitivities.isEmpty()) {
+            return postContent;
+        }
+        // 解析 HTML
+        Document doc = Jsoup.parseBodyFragment(postContent);
+        // 遍历所有节点
+        NodeTraversor.traverse(new NodeVisitor() {
+            @Override
+            public void head(org.jsoup.nodes.Node node, int depth) {
+                if (node instanceof TextNode) {
+                    TextNode textNode = (TextNode) node;
+                    String text = textNode.text();
+                    if (text.contains("data:image") || text.contains("base64")) {
+                        return;
+                    }
+                    org.jsoup.nodes.Node nodeParent = textNode.parent();
+                    if (nodeParent instanceof Element) {
+                        Element parent = (Element) nodeParent;
+                        String tag = parent.tagName().toLowerCase();
+                        if ("script".equals(tag) || "style".equals(tag)) {
+                            return;
+                        }
+                    }
+                    // 遍历敏感词进行替换
+                    String newText = text;
+                    for (ForumSensitivity s : forumSensitivities) {
+                        String word = s.getSensitivityWord();
+                        if (word == null || word.trim().isEmpty()) {
+                            continue;
+                        }
+                        Pattern pattern = Pattern.compile(
+                                "\\b" + Pattern.quote(word) + "\\b",
+                                Pattern.CASE_INSENSITIVE
+                        );
+                        Matcher matcher = pattern.matcher(newText);
+                        if (matcher.find()) {
+                            newText = matcher.replaceAll("****");
+                            // 记录数据库
+                            ForumSensitivityRecord record = new ForumSensitivityRecord();
+                            record.setSensitivityWord(word);
+                            record.setUserId(loginUser.getId());
+                            record.setRecordType(0);
+                            record.setPostId(uuid);
+                            forumSensitivityRecordMapper.insert(record);
+                        }
+                    }
+                    // 更新节点文本
+                    if (!newText.equals(text)) {
+                        textNode.text(newText);
+                    }
                 }
             }
-        }
-        return postContent;
+
+            @Override
+            public void tail(org.jsoup.nodes.Node node, int depth) {
+                // 不用处理
+            }
+        }, doc.body());
+
+        // 返回完整 HTML
+        return doc.body().html();
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -297,7 +372,9 @@ public class ForumPostInfoServiceImpl extends ServiceImpl<ForumPostInfoMapper, F
         }
         // 确认标题是否有敏感词,有直接拦截(标题)
         String titleIsIllegal = filterSensitiveWordsTitle(forumPostInfoEditParam.getPostTitle());
-        if("1".equals(titleIsIllegal))return CommonResult.error("帖子标题含有敏感词");
+        if("1".equals(titleIsIllegal)) {
+            return CommonResult.error("帖子标题含有敏感词");
+        }
         // 过滤敏感词(内容)
         String postContent = filterSensitiveWords(forumPostInfoEditParam.getPostContent(), loginUser, forumPostInfoEditParam.getPostId());
         forumPostInfoEditParam.setPostContent(postContent);