IM 安全通(内容安全审核)

更新时间: 2023/06/29 09:02:48

网易云信 IM 安全通(内容安全审核)服务,融合了网易易盾的内容审核能力,支持对文本消息、图片消息、自定义消息、用户头像和用户资料等类型的内容安全检测,实现全流程的审-查-禁功能,降低人力投入。

功能介绍

开通安全通功能并配置安全通检测规则后,指定类型的消息经过相关的接口调用和配置后,都会先经由安全通进行内容安全检测,之后才会转发给接收端的用户。安全通支持如下几种消息类型的内容审核。

API 关键字 说明
text 文本消息
image 图片消息
audio 音频消息
video 视频消息
avchat 音视频通话事件消息
notification 通知消息
tip 提醒消息
custom 自定义消息

技术原理

针对不同的内容类型,安全通提供两套内容审核方案:

审核方案
说明
实时(同步)内容审核 主要针对文本内容。由云信服务端进行内容提交、过滤和投递,客户端会收到内容审核结果,且云信服务器会同时抄送审核结果给应用服务器。客户端上需根据内容审核结果自行实现相关业务处理。
异步内容审核 主要针对音频、视频。由云信服务端先行投递消息,违规内容由云信服务端删除。内容审核结果抄送至应用服务器,后者根据审核结果对消息进行处理(如撤回)。客户端不会收到内容审核结果

若您需要云信服务器将审核结果抄送到您的应用服务器,即上图中的流程 6,请先开通易盾异步反垃圾抄送

实现流程

graph LR
    %% 定义样式类
    classDef default fill:#337EFF,stroke:#337EFF,stroke-width:1px,color:#FFFFFF;

    开通安全通 --> 配置安全通检测规则 --> 实现安全通审核 --> 获取审核结果 --> 处理安全审核结果

步骤1:开通安全通并配置安全通检测规则

  1. 开通安全通,具体步骤请参见开通能力
  2. 在控制台首页选择对应的应用,在左侧导航栏选择 产品功能 > IM 即时通讯,顶部选择安全通页签,单击子功能配置

IM安全通.png

  1. 配置内容安全抄送地址。

    接收 IM 内容审核结果的抄送地址与 IM、音视频通话 2.0 的消息抄送地址相同,若您此前从未开通抄送功能、未配置抄送地址,请单击前往配置,配置抄送地址。

    如果您已经开通了抄送功能,此处默认使用同一个抄送地址。

    内容安全抄送地址.png

  2. 配置内容安全范围。

    单击具体审核类型的配置选择需要的模块。

    IM内容安全配置.png

    配置内容审核模块.png

  3. 配置内容安全疑似处理规则。

    单击具体业务的配置进行过审内容和疑似处理配置。

    疑似处理配置.png

步骤2:配置关键词名单

您可以配置关键词名单,对文本消息中的敏感词进行检测。

  1. 在网易云信控制台的IM 安全通配置 页面底部,单击更多安全配置

    IM安全通更多安全配置.png

  2. 在易盾智能审核平台左侧导航栏选择策略配置 > 关键词名单,将需要检测的敏感词添加到关键词清单中。

    易盾控制台.png

步骤3:实现安全通审核

开通安全通服务后,调用发送消息方法时传入相关参数(NIMAntiSpamOption)可实现消息内容过安全通审核。指定类型的消息会根据检测规则进行内容安全检测。

json{
    "type": 1, //1:文本,2:图片
    "data": "" //文本内容or图片地址
}

示例代码

java// 该帐号为示例,请先注册
String account = "testAccount";
// 以单聊类型为例
SessionTypeEnum sessionType = SessionTypeEnum.P2P;
String text = "这条不需要过安全通";
// 创建一个文本消息
IMMessage textMessage = MessageBuilder.createTextMessage(account, sessionType, text);

// 构造反垃圾对象
NIMAntiSpamOption antiSpamOption = new NIMAntiSpamOption();
antiSpamOption.enable = false;
textMessage.setNIMAntiSpamOption(antiSpamOption);

// 发送给对方
NIMClient.getService(MsgService.class).sendMessage(textMessage, false);

步骤4:获取审核结果

匹配消息体命中敏感词后,可通过 IMMessage#getYidunAntiSpamRes 字段通知客户端结果,该字段需要通过 observeMsgStatus 回调获取。

只有被安全通拦截的消息才会有yidunAntiSpamRes返回。对于疑似消息根据云信控制台设置的策略来判断,如果疑似消息被拦截会有yidunAntiSpamRes返回,如果疑似消息放行则没有yidunAntiSpamRes返回。

返回的审核结果 yidunAntiSpamRes 为 JSON 字符串格式,请自行解析或者反转成 JSON 对象使用。

yidunAntiSpamRes 字段定义如下:

名称类型说明
code Integer状态码:
  • 200:易盾内容审核结果返回正常
  • 404:易盾反回的内容审核结果为空,该情况下 yidunAntiSpamRes 中无 code 以外的字段
  • 414:易盾返回的内容审核结果过长,该情况下 yidunAntiSpamRes 中无 ext 字段
type String内容审核类型
  • text:文本
  • image:图片
version String易盾内容审核的接口版本
taskId String审核任务的 ID
suggestion Integer 建议处理方式
  • 0:通过
  • 1:嫌疑,建议人工复审
  • 2:不通过
status Integer内容审核请求结果
  • 0:成功
  • 1:失败
ext String内容审核结果,对应易盾的 result 字段,result 字段详情参见易盾文档(注:本链接仅以“单次同步文本检测的 result 字段说明”为例)
语音、视频消息进行安全通反垃圾时,是异步检测的,并且检测结果是通过 IM 抄送通知开发者服务器。虽然命中后云信会自动删除服务器上的文件,但是在检测结果出来之前,消息可能已经被投递到接收方。因此如果开发者收到命中抄送后,请通过 IM 服务端接口进行消息撤回

安全通重要参数

参数 类型 说明
yidunAntiSpamExt 易盾反垃圾扩展字段 透传给易盾的反垃圾增强版的检测参数,具体请参见易盾的反垃圾增强版用户可扩展参数,格式为json,长度限制1024 反作弊相关的email、phone、token、extension,抄送到yidunAntiCheating。其他用户增值信息,抄送到yidunAntiSpamExt。
yidunAntiSpamRes 易盾反垃圾结果 易盾反垃圾触发时返回的结果字段,格式为json
yidunAntiCheating 易盾反作弊字段 透传给易盾的反作弊检测参数,格式为json,长度限制1024 ,具体请参见文本防刷版开发文档反作弊相关的email、phone、token、extension,抄送到yidunAntiCheating。其他用户增值信息,抄送到yidunAntiSpamExt。

示例代码

 Observer<IMMessage> statusMessage =
      (Observer<IMMessage>)
          message -> {
            if (!TextUtils.isEmpty(message.getYidunAntiSpamRes())) {
                  
              JSONObject jsonObject = null;
              try {
                jsonObject = new JSONObject(message.getYidunAntiSpamRes());
                String ext = jsonObject.optString("ext");
                // 安全违规消息
              } catch (JSONException e) {
                e.printStackTrace();
              }
            }
          };
 NIMClient.getService(MsgServiceObserve.class).observeMsgStatus(statusMessage, true);

步骤5:处理安全审核结果

当消息体命中敏感词后,在客户端页面展示类似下图的消息通知。

消息系统2.png

您可以通过 IM 自定义消息 实现该功能,实现方法如下:

    // 注册自定义消息解析器
    ChatKitClient.addCustomAttach(
        OneOnOneChatCustomMessageType.PRIVACY_RISK_MESSAGE_TYPE, PrivacyRiskAttachment.class);
    ChatKitClient.addCustomAttach(
        OneOnOneChatCustomMessageType.COMMON_RISK_MESSAGE_TYPE, CommonRiskAttachment.class);
   // 注册自定义消息视图
  ChatKitClient.addCustomViewHolder(
        OneOnOneChatCustomMessageType.PRIVACY_RISK_MESSAGE_TYPE,
        PrivacyRiskMessageViewHolder.class);
    ChatKitClient.addCustomViewHolder(
        OneOnOneChatCustomMessageType.COMMON_RISK_MESSAGE_TYPE, CommonRiskMessageViewHolder.class);


   // 监听消息
     private final EventObserver<IMMessageInfo> msgObserver =
      new EventObserver<IMMessageInfo>() {
        @Override
        public void onEvent(@Nullable IMMessageInfo event) {
          handleRiskMessage(event);
        }
      };     

private void handleRiskMessage(IMMessageInfo event) {
    if (event != null && !TextUtils.isEmpty(event.getMessage().getYidunAntiSpamRes())) {
      boolean isHitCustomWords = false;
      if (event.getMessage().getMsgType() == MsgTypeEnum.text) {
        String yidunAntiSpamRes = event.getMessage().getYidunAntiSpamRes();
        try {
          JSONObject jsonObject = new JSONObject(yidunAntiSpamRes);
          String ext = jsonObject.optString("ext");
          ALog.i(TAG, "ext:" + ext);
          YidunAntiSpamResModel.ExtBean extBean =
              GsonUtils.fromJson(ext, YidunAntiSpamResModel.ExtBean.class);
          if (extBean != null
              && extBean.getAntispam() != null
              && extBean.getAntispam().getLabels() != null
              && !extBean.getAntispam().getLabels().isEmpty()) {
            for (YidunAntiSpamResModel.ExtBean.AntispamBean.LabelsBean label :
                extBean.getAntispam().getLabels()) {
              List<YidunAntiSpamResModel.ExtBean.AntispamBean.LabelsBean.SubLabelsBean> subLabels =
                  label.getSubLabels();
              if (subLabels != null && !subLabels.isEmpty()) {
                for (YidunAntiSpamResModel.ExtBean.AntispamBean.LabelsBean.SubLabelsBean subLabel :
                    subLabels) {
                  if (subLabel.getDetails() != null
                      && subLabel.getDetails().getKeywords() != null
                      && !subLabel.getDetails().getKeywords().isEmpty()) {
                    List<
                            YidunAntiSpamResModel.ExtBean.AntispamBean.LabelsBean.SubLabelsBean
                                .DetailsBean.KeywordsBean>
                        keywords = subLabel.getDetails().getKeywords();
                    for (YidunAntiSpamResModel.ExtBean.AntispamBean.LabelsBean.SubLabelsBean
                            .DetailsBean.KeywordsBean
                        keyword : keywords) {
                      if (keyword != null && !TextUtils.isEmpty(keyword.getWord())) {
                        isHitCustomWords = true;
                        break;
                      }
                    }
                  }
                }
              }
            }
          }

        } catch (JSONException e) {
          e.printStackTrace();
          ALog.e(TAG, "e:" + e);
        }
        if (isHitCustomWords) {
            // 插入隐私提醒本地消息
          mainHandler.postDelayed(() -> ChatUtil.insertPrivacyRiskMessage(sessionId), DELAY_TIME);
        } else {
            // 插入安全提醒本地消息
          mainHandler.postDelayed(() -> ChatUtil.insertCommonRiskMessage(sessionId), DELAY_TIME);
        }
      } else {
           // 插入安全提醒本地消息
        mainHandler.postDelayed(() -> ChatUtil.insertCommonRiskMessage(sessionId), DELAY_TIME);
      }
    }
  }
此文档是否对你有帮助?
有帮助
去反馈
  • 功能介绍
  • 技术原理
  • 实现流程
  • 步骤1:开通安全通并配置安全通检测规则
  • 步骤2:配置关键词名单
  • 步骤3:实现安全通审核
  • 步骤4:获取审核结果
  • 步骤5:处理安全审核结果