主题
敏感词过滤 Skill
硬规则
- 玩家产生且会被其他玩家看到、保存或转发的文本,必须先在服务端调用
Game.FilterSensitiveWords。 - 不要依赖客户端过滤。客户端只能用于即时提示,服务端结果才可作为后续广播、持久化或跨服转发的输入。
ServerChannel是服务端之间的发布/订阅消息传输机制。channel 是消息主题或路由标识,不是玩家聊天房间;载荷不会被自动检查或过滤。- 使用
ServerChannelMessage.Publish/PublishToUser开发跨服聊天时,先过滤玩家文本,再构造和发送消息。 DualEndEvent、TypedMessage、ProtoCustomMessage同样只负责传输,不自动过滤玩家文本。- 不要把
WasFiltered == false当成服务可用性判定。它只表示本次没有发生替换。 - 不要在日志、云数据、排行榜、邮件、频道消息或审计事件中继续使用过滤前的玩家文本,除非项目有明确且合规的受控审计方案。
服务端处理顺序
- 校验发送者身份、权限、频率、空文本和长度。
- 调用
Game.FilterSensitiveWords(input)。 - 按产品策略选择替换或拒绝。
- 仅使用
FilteredText广播、持久化或跨服发送。 - 客户端只显示服务端确认后的文本。
csharp
#if SERVER
var result = Game.FilterSensitiveWords(playerText);
// 替换策略:继续发送已过滤文本。
var safeText = result.FilteredText;
// 拒绝策略:命中时停止提交,并向客户端返回项目定义的提示。
if (result.WasFiltered)
{
return false;
}
#endifServerChannel 边界
下面的写法不会触发任何自动内容审核:
csharp
ServerChannelMessage.PublishToUser(targetUserId, "private-message", payload);如果 payload 包含玩家文本,应在来源服务器先过滤:
csharp
#if SERVER
var filterResult = Game.FilterSensitiveWords(input);
var payload = new CrossServerChatMessage
{
SenderUserId = senderUserId,
Content = filterResult.FilteredText
};
ServerChannelMessage.PublishToUser(targetUserId, "private-message", payload);
#endif接收端如果可能收到旧版本服务器或其他未受信任来源的消息,可在展示给玩家前再次过滤。不要把消息主题名包含 chat 误认为系统会识别聊天语义。
审查清单
- [ ] 玩家文本在服务端过滤,而不是只在客户端过滤
- [ ] 广播、存储和跨服发送使用
FilteredText - [ ] 昵称、公会名、房间名和留言等非聊天文本也纳入检查
- [ ] ServerChannel 代码没有假设传输层会自动过滤
- [ ] 已处理长度、频率、权限和重复发送;敏感词过滤不是完整的反滥用系统
- [ ] 没有把过滤前文本写入普通日志或不受控存储
相关文档
docs/systems/SensitiveWordFilterSystem.mddocs/systems/ServerChannelSystem.mddocs/systems/DualEndEventSystem.md