添加配置敏感词检查用户昵称/群组名/群备注等信息

This commit is contained in:
heavyrian2012
2025-08-05 15:32:20 +08:00
parent 59b1c3180f
commit bee03cd2f8
8 changed files with 62 additions and 2 deletions
+4
View File
@@ -448,6 +448,10 @@ push.harmony.server.address http://localhost:8085/harmony/push
## 如果开启 message.sensitive.forward.url 配置,命中敏感词的消息还会被回调到这个地址 ## 如果开启 message.sensitive.forward.url 配置,命中敏感词的消息还会被回调到这个地址
sensitive.filter.type 2 sensitive.filter.type 2
## 敏感词是否只处理消息。如果为true,只过滤消息;如果为false,会同时过滤用户昵称、群组名和群昵称。
## 除了消息之外的信息只支持内部敏感词处理,不支持外置审核。
sensitive.only_message false
## 敏感词添加或者删除有2种方式,一种是通过Server API进行,这种方式会立即生效。另外一种方法是修改数据库,直接中数据库的t_sensitive_word表中处理 ## 敏感词添加或者删除有2种方式,一种是通过Server API进行,这种方式会立即生效。另外一种方法是修改数据库,直接中数据库的t_sensitive_word表中处理
## 修改数据库的方法不会立即生效,IM服务会2个小时重新加载一次敏感词。所以如果直接修改敏感词表,需要等2个小时,或者重启才能生效。 ## 修改数据库的方法不会立即生效,IM服务会2个小时重新加载一次敏感词。所以如果直接修改敏感词表,需要等2个小时,或者重启才能生效。
@@ -124,7 +124,7 @@ public final class BrokerConstants {
public static final String SENSITIVE_Filter_Type = "sensitive.filter.type"; public static final String SENSITIVE_Filter_Type = "sensitive.filter.type";
public static final String SENSITIVE_Only_Message = "sensitive.only_message";
public static final String SENSITIVE_Remote_Server_URL = "sensitive.remote_server_url"; public static final String SENSITIVE_Remote_Server_URL = "sensitive.remote_server_url";
public static final String SENSITIVE_Remote_Message_Type = "sensitive.remote_sensitive_message_type"; public static final String SENSITIVE_Remote_Message_Type = "sensitive.remote_sensitive_message_type";
public static final String SENSITIVE_Remote_Fail_When_Matched = "sensitive.remote_fail_when_matched"; public static final String SENSITIVE_Remote_Fail_When_Matched = "sensitive.remote_fail_when_matched";
@@ -19,6 +19,7 @@ import win.liyufan.im.IMTopic;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
@Handler(value = IMTopic.CreateGroupTopic) @Handler(value = IMTopic.CreateGroupTopic)
public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupRequest> { public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupRequest> {
@@ -68,6 +69,13 @@ public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupReque
return ErrorCode.INVALID_PARAMETER; return ErrorCode.INVALID_PARAMETER;
} }
if(!m_messagesStore.isSensitiveOnlyMessage() && !isAdmin && !StringUtil.isNullOrEmpty(request.getGroup().getGroupInfo().getName())) {
Set<String> matched = m_messagesStore.handleSensitiveWord(request.getGroup().getGroupInfo().getName());
if (matched != null && !matched.isEmpty()) {
return ErrorCode.ERROR_CODE_SENSITIVE_MATCHED;
}
}
WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), request.getMemberExtra(), isAdmin, failedMembers); WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), request.getMemberExtra(), isAdmin, failedMembers);
if (groupInfo != null && groupInfo.getDeleted() == 0) { if (groupInfo != null && groupInfo.getDeleted() == 0) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
@@ -11,11 +11,14 @@ package io.moquette.imhandler;
import cn.wildfirechat.proto.ProtoConstants; import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage; import cn.wildfirechat.proto.WFCMessage;
import cn.wildfirechat.pojos.GroupNotificationBinaryContent; import cn.wildfirechat.pojos.GroupNotificationBinaryContent;
import com.hazelcast.util.StringUtil;
import io.moquette.spi.impl.Qos1PublishHandler; import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import cn.wildfirechat.common.ErrorCode; import cn.wildfirechat.common.ErrorCode;
import win.liyufan.im.IMTopic; import win.liyufan.im.IMTopic;
import java.util.Set;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS; import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
@Handler(IMTopic.ModifyGroupAliasTopic) @Handler(IMTopic.ModifyGroupAliasTopic)
@@ -26,10 +29,18 @@ public class ModifyGroupAliasHandler extends GroupHandler<WFCMessage.ModifyGroup
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && requestSourceType == ProtoConstants.RequestSourceType.Request_From_User && !m_messagesStore.isAllowClientCustomGroupNotification()) { if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && requestSourceType == ProtoConstants.RequestSourceType.Request_From_User && !m_messagesStore.isAllowClientCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && requestSourceType == ProtoConstants.RequestSourceType.Request_From_Robot && !m_messagesStore.isAllowRobotCustomGroupNotification()) { if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && requestSourceType == ProtoConstants.RequestSourceType.Request_From_Robot && !m_messagesStore.isAllowRobotCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if (!m_messagesStore.isSensitiveOnlyMessage() && !isAdmin && !StringUtil.isNullOrEmpty(request.getAlias())) {
Set<String> matched = m_messagesStore.handleSensitiveWord(request.getAlias());
if (matched != null && !matched.isEmpty()) {
return ErrorCode.ERROR_CODE_SENSITIVE_MATCHED;
}
}
ErrorCode errorCode = m_messagesStore.modifyGroupMemberAlias(fromUser, request.getGroupId(), request.getAlias(), null, isAdmin); ErrorCode errorCode = m_messagesStore.modifyGroupMemberAlias(fromUser, request.getGroupId(), request.getAlias(), null, isAdmin);
if (errorCode == ERROR_CODE_SUCCESS) { if (errorCode == ERROR_CODE_SUCCESS) {
if (request.hasNotifyContent()&& request.getNotifyContent().getType() > 0) { if (request.hasNotifyContent()&& request.getNotifyContent().getType() > 0) {
@@ -12,10 +12,13 @@ import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.GroupNotificationBinaryContent; import cn.wildfirechat.pojos.GroupNotificationBinaryContent;
import cn.wildfirechat.proto.ProtoConstants; import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage; import cn.wildfirechat.proto.WFCMessage;
import com.hazelcast.util.StringUtil;
import io.moquette.spi.impl.Qos1PublishHandler; import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import win.liyufan.im.IMTopic; import win.liyufan.im.IMTopic;
import java.util.Set;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS; import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
@Handler(IMTopic.ModifyGroupMemberAliasTopic) @Handler(IMTopic.ModifyGroupMemberAliasTopic)
@@ -29,6 +32,12 @@ public class ModifyGroupMemberAliasHandler extends GroupHandler<WFCMessage.Modif
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && requestSourceType == ProtoConstants.RequestSourceType.Request_From_Robot && !m_messagesStore.isAllowRobotCustomGroupNotification()) { if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && requestSourceType == ProtoConstants.RequestSourceType.Request_From_Robot && !m_messagesStore.isAllowRobotCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if (!m_messagesStore.isSensitiveOnlyMessage() && !isAdmin && !StringUtil.isNullOrEmpty(request.getAlias())) {
Set<String> matched = m_messagesStore.handleSensitiveWord(request.getAlias());
if (matched != null && !matched.isEmpty()) {
return ErrorCode.ERROR_CODE_SENSITIVE_MATCHED;
}
}
ErrorCode errorCode = m_messagesStore.modifyGroupMemberAlias(fromUser, request.getGroupId(), request.getAlias(), request.getMemberId(), isAdmin); ErrorCode errorCode = m_messagesStore.modifyGroupMemberAlias(fromUser, request.getGroupId(), request.getAlias(), request.getMemberId(), isAdmin);
if (errorCode == ERROR_CODE_SUCCESS) { if (errorCode == ERROR_CODE_SUCCESS) {
@@ -171,7 +171,7 @@ public class MemoryMessagesStore implements IMessagesStore {
private boolean mGroupAllowPartSuccess = false; private boolean mGroupAllowPartSuccess = false;
private boolean mIDUseUUID = true; private boolean mIDUseUUID = true;
private boolean mSensitiveOnlyMessage = true;
private Set<String> mClientSignatureSet = new HashSet<>(); private Set<String> mClientSignatureSet = new HashSet<>();
private boolean mRejectEmptySignature = true; private boolean mRejectEmptySignature = true;
@@ -671,6 +671,11 @@ public class MemoryMessagesStore implements IMessagesStore {
mIDUseUUID = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.ID_USE_UUID, "false")); mIDUseUUID = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.ID_USE_UUID, "false"));
} catch (Exception e) { } catch (Exception e) {
} }
try {
mSensitiveOnlyMessage = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SENSITIVE_Only_Message, "true"));
} catch (Exception e) {
}
} }
private void printMissConfigLog(String config, String defaultValue) { private void printMissConfigLog(String config, String defaultValue) {
@@ -1974,6 +1979,13 @@ public class MemoryMessagesStore implements IMessagesStore {
if (!isAllow) { if (!isAllow) {
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if (!mSensitiveOnlyMessage && modifyType == Modify_Group_Name && !StringUtil.isNullOrEmpty(value)) {
Set<String> matched = handleSensitiveWord(value);
if (matched != null && !matched.isEmpty()) {
return ErrorCode.ERROR_CODE_SENSITIVE_MATCHED;
}
}
} }
if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Normal) { if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Normal) {
@@ -2810,6 +2822,12 @@ public class MemoryMessagesStore implements IMessagesStore {
) { ) {
switch (entry.getType()) { switch (entry.getType()) {
case Modify_DisplayName: case Modify_DisplayName:
if(!mSensitiveOnlyMessage) {
Set<String> matched = handleSensitiveWord(entry.getValue());
if (matched != null && !matched.isEmpty()) {
return ErrorCode.ERROR_CODE_SENSITIVE_MATCHED;
}
}
builder.setDisplayName(entry.getValue()); builder.setDisplayName(entry.getValue());
modified = true; modified = true;
break; break;
@@ -4770,6 +4788,11 @@ public class MemoryMessagesStore implements IMessagesStore {
return new ArrayList<>(databaseStore.getSensitiveWord()); return new ArrayList<>(databaseStore.getSensitiveWord());
} }
@Override
public boolean isSensitiveOnlyMessage() {
return mSensitiveOnlyMessage;
}
@Override @Override
public WFCMessage.Message getMessage(long messageId) { public WFCMessage.Message getMessage(long messageId) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance(); HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
@@ -232,6 +232,7 @@ public interface IMessagesStore {
boolean addSensitiveWords(List<String> words); boolean addSensitiveWords(List<String> words);
boolean removeSensitiveWords(List<String> words); boolean removeSensitiveWords(List<String> words);
List<String> getAllSensitiveWords(); List<String> getAllSensitiveWords();
boolean isSensitiveOnlyMessage();
WFCMessage.Message getMessage(long messageId); WFCMessage.Message getMessage(long messageId);
@@ -455,6 +455,10 @@ push.harmony.server.address http://localhost:8085/harmony/push
## 如果开启 message.sensitive.forward.url 配置,命中敏感词的消息还会被回调到这个地址 ## 如果开启 message.sensitive.forward.url 配置,命中敏感词的消息还会被回调到这个地址
sensitive.filter.type 2 sensitive.filter.type 2
## 敏感词是否只处理消息。如果为true,只过滤消息;如果为false,会同时过滤用户昵称、群组名和群昵称。
## 除了消息之外的信息只支持内部敏感词处理,不支持外置审核。
sensitive.only_message false
## 敏感词添加或者删除有2种方式,一种是通过Server API进行,这种方式会立即生效。另外一种方法是修改数据库,直接中数据库的t_sensitive_word表中处理 ## 敏感词添加或者删除有2种方式,一种是通过Server API进行,这种方式会立即生效。另外一种方法是修改数据库,直接中数据库的t_sensitive_word表中处理
## 修改数据库的方法不会立即生效,IM服务会2个小时重新加载一次敏感词。所以如果直接修改敏感词表,需要等2个小时,或者重启才能生效。 ## 修改数据库的方法不会立即生效,IM服务会2个小时重新加载一次敏感词。所以如果直接修改敏感词表,需要等2个小时,或者重启才能生效。