V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
CloudStorage
V2EX  ›  推广

内容审核实践 | 即时通讯 IM 场景

  •  
  •   CloudStorage · 2021-09-27 12:19:08 +08:00 · 1012 次点击
    这是一个创建于 1145 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一、概述

    一些用户使用即时通信 IM 产品开发实现自己的聊天业务,但对于聊天之间的消息无法很好的去管控内容是否违规。

    基于数据万象 CI,对象存储 COS 推出的内容审核功能,可以帮助用户实现 IM 消息的审核服务,在发送出来的消息是违规内容时,不允许发送(先审后发)。

    整体流程可看下图:

    内容审核的处理主要在步骤 6 、7 、8 。

    步骤 6:发送审核请求对消息内容进行审核。 步骤 7:返回处理结果。 步骤 8:根据结果判断是否发送消息或是否撤回、删除消息。

    实际聊天效果如下图:

    二、准备工作

    (一)即时通信 IM 简单 DEMO

    [ Demo 入门] 一分钟跑通 Demo: https://cloud.tencent.com/document/product/269/36838 IM SDK 地址: https://cloud.tencent.com/document/product/269/36887

    按照文档说明登陆、 获取 SDKAppID 及密钥信息、 创建应用、 下载 DEMO 源码、 配置密钥、 编译运行(部分平台需要)

    本文例子使用 Web&H5,修改 GenerateTestUserSig.js 文件配置密钥后,无需编译,可直接访问 dist/index.html, 如: http://127.0.0.1/timSdkH5Demo/dist/index.html 替换服务器地址后可以直接访问,timSdkH5Demo 为代码目录,可按需修改。 访问后显示如下页面,可下拉选择用户登陆,两个用户登陆不同账号即可实现聊天功能。

    (二) IM 配置项

    登录 即时通信 IM 控制台—回调配置
    回调 URL 配置 >> 编辑:填写回调 URL 后确认保存。具体回调参数及说明可访问 第三方回调简介 。

    事件回调配置 >> 编辑:选择需要的回调事件,以“单聊消息”为例,选中 “发单聊消息之前回调”,会在发送消息前请求回调 URL,一系列判断后返回回调结果。

    注意:回调 URL 需公网可见。

    这一步需要保证的就是,即时通信 IM 可实现消息发送、即时通信 IM 控制台回调配置完成,且在发送消息时触发回调 URL 的请求,回调接口能够接收到请求数据。强调:回调 URL 接口需公网可见。

    三、文字消息审核具体配置

    目前准备工作已经做好了,接下来需要考虑的有以下几点:

    消息发送时回调接口接收请求参数,确认参数的准确性。

    根据不同参数获取到不同消息内容,如:聊天文本、图片地址等。

    对消息内容进行审核,不同的消息类型会调用不同的审核接口,接下来的内容会对不同的消息类型(文本和图片)进行举例说明。

    根据审核结果给出不同的返回结果,达到消息是否允许发送的效果。

    Ps: 下面举例说明部分会以 Step n 来对应上面各点。

    以下举例说明都是以审核 IM 消息内容为前提,如需审核其他内容,可见各审核文档的详细介绍。

    举例说明:

    开发工具:SCF 云函数 https://console.cloud.tencent.com/scf (不一定非要云函数,服务公网可见即可,否则回调请求失败)
    语言:PHP/7.2.2
    
    通信 IM SDK 以及 Demo 源码:
    地址: https://cloud.tencent.com/document/product/269/36887 
    本文档例子使用 Web&H5: https://github.com/tencentyun/TIMSDK/tree/master/H5
    
    对象存储 SDK 文档:
    PHP SDK 地址: https://cloud.tencent.com/document/product/436/12266 (其他语言可见页面左侧栏对应标签)
    
    IM 配置项:
    单聊消息 >> 发单聊消息之前回调
    
    举例消息类型:
    文本、图片
    

    Step 1 回调请求参数

    第三方回调简介: https://cloud.tencent.com/document/product/269/1522

    回调参数列表: https://cloud.tencent.com/document/product/269/1523

    消息格式描述: https://cloud.tencent.com/document/product/269/2720

    IM 发送消息后会请求回调 URL,本例中对 SdkAppid 参数做了简单身份验证,如需要其他复杂验证可自行判断。

    <?php
    
    include_once 'commonFunc.php'; // 自定义公用函数,如发送 POST 、GET 请求或做出 Response 响应等函数的封装
    include_once 'imMsg.php'; // 自定义消息审核类,对文本和图片做出审核请求并对审核结果做出是否违规判断
    include_once 'cos-php-sdk-v5-master/vendor/autoload.php'; // COS 内容审核 SDK 引入,本例使用 PHP 的 SDK
    
    $content = file_get_contents('php://input'); // 获取 POST JSON 数据 字符串
    $post  = json_decode($content, true); // POST JSON 数据 数组
    
    // 对 SdkAppid 做出简单身份验证
    if(!isset($_GET['SdkAppid']) || $_GET['SdkAppid'] != ImMsg::SDK_APPID) {
        imcallback_return(false); // 接口返回结果数据
    }
    
    **
     * 函数内列出两种回调结果
     * $send true 允许消息发送; false 禁止消息发送
     */
    function imcallback_return($send = true) {
        $retSuccess = array(
            'ErrorCode' => 0, // 0 为允许发言
            'ErrorInfo' => '',
            'ActionStatus' => 'OK'
        );;
        $retErr = array(
            'ErrorCode' => 1, // 1 为拒绝发言
            'ErrorInfo' => 'err',
            'ActionStatus' => 'FAIL'
        );
        $ret = $send === true ? $retSuccess : $retErr;
        ob_clean();
        echo json_encode($ret);
    }
    

    回调请求示例:

    POST /?SdkAppid=123456&CallbackCommand=C2C.CallbackBeforeSendMsg&contenttype=json&ClientIP&OptPlatform HTTP/1.1
    Host: www.example.com
    文本类型:
    {
        "MsgBody": [
            {
                "MsgType": "TIMTextElem", // TIMTextElem 表示消息类型为文本
                "MsgContent": {
                    "Text": "asdad" // 文本内容
                }
            }
        ],
        "CallbackCommand": "C2C.CallbackBeforeSendMsg", // C2C.CallbackBeforeSendMsg 发单聊消息之前回调
        "From_Account": "user1",
        "To_Account": "user0",
        "MsgRandom": 123,
        "MsgSeq": 1234567,
        "MsgTime": 1629439393,
        "MsgKey": "1234567_123456_123456789",
        "OnlineOnlyFlag": 0
    }
    
    图片类型:
    {
        "MsgBody": [
            {
                "MsgType": "TIMImageElem", // TIMImageElem 表示消息类型为图片
                "MsgContent": {
                    "UUID": "123456-user1-abcdefghd", 
                    "ImageFormat": 3, 
                    "ImageInfoArray": [
                        {
                            "Type": 1, //原图
                            "Size": 43599, 
                            "Width": 1156, 
                            "Height": 582, 
                            "URL": "https://cos.ap-shanghai.myqcloud.com/6244-shanghai-007-shared-01-1256635546/2690-1400560394/e078-user1/582eef3bb1e6439cd842ae0bd6a16cae-101935?imageMogr2/"
                        }, 
                        {
                            "Type": 2, //大图
                            "Size": 0, 
                            "Width": 0, 
                            "Height": 0, 
                            "URL": "https://cos.ap-shanghai.myqcloud.com/6244-shanghai-007-shared-01-1256635546/2690-1400560394/e078-user1/582eef3bb1e6439cd842ae0bd6a16cae-101935?imageMogr2/"
                        }, 
                        {
                            "Type": 3, //缩量图
                            "Size": 0, 
                            "Width": 394, 
                            "Height": 198, 
                            "URL": "https://cos.ap-shanghai.myqcloud.com/6244-shanghai-007-shared-01-1256635546/2690-1400560394/e078-user1/582eef3bb1e6439cd842ae0bd6a16cae-101935?imageMogr2/&imageView2/3/w/198/h/198"
                        }
                    ]
                }
            }
        ], 
        "CallbackCommand": "C2C.CallbackBeforeSendMsg", 
        "From_Account": "user1", 
        "To_Account": "user0", 
        "MsgRandom": 123, 
        "MsgSeq": 1234567, 
        "MsgTime": 1629357746, 
        "MsgKey": "1234567_123456_123456789", 
        "OnlineOnlyFlag": 0
    }
    

    回调应答示例:

    HTTP/1.1 200 OK
    Server: nginx/1.7.10
    Date: Fri, 09 Oct 2015 02:59:55 GMT
    Content-Length: 75
    {
      "ActionStatus": "OK", 
      "ErrorInfo": "", 
      "ErrorCode": 0 // 1 为拒绝发言; 0 为允许发言
    }
    

    即时通信 IM 回调 App 后台的超时时间为 2 秒,且没有重试。如果回调超时,后续处理逻辑与没有配置回调时相同(例如,假设“发送群消息之前回调”超时,消息会正常下发)。

    为确保回调成功率,第三方 App 应当尽可能加快回调处理速度,例如先发送回调应答,然后再处理具体业务逻辑。

    Step 2 获取消息内容

    回调类型 回调命令字
    发单聊消息之前回调 C2C.CallbackBeforeSendMsg
    发单聊消息之后回调 C2C.CallbackAfterSendMsg

    其他回调命令及相关参数见 回调命令列表。

    MsgType 的值 类型
    TIMTextElem 文本消息
    TIMImageElem 图像消息

    其他消息类别 MsgType 描述及相关参数见 消息格式描述。

    本例中简单获取了文本内容及图片地址 URL 。

    $flag = false;
    switch($_GET['CallbackCommand']) {
        case 'C2C.CallbackBeforeSendMsg': { // 对发单聊消息之前回调进行封装
            $flag = ImMsg::cmdC2cMsgBefore($post);
            break;
        }
        default: {
            break;
        }
    }
    imcallback_return($flag);
    
    ImMsg::cmdC2cMsgBefore
    public static function cmdC2cMsgBefore($allData) {
        $data = $allData['MsgBody'];
        $flag = true;
        foreach($data as $msgItem) {
            if($msgItem['MsgType'] == 'TIMTextElem') { // 文本类型审核
                // $msgItem['MsgContent']['Text'] 文本内容
                $flag = self::textDetect($msgItem['MsgContent']['Text']); 
            } else if($msgItem['MsgType'] == 'TIMImageElem') { // 图片类型审核
                // $msgItem['MsgContent']['ImageInfoArray'][0]['URL'] 图片 URL 地址,原图、大图、缩略图三选一
                $flag = self::imgDetect($msgItem['MsgContent']['ImageInfoArray'][0]['URL']);
            }
        }
        return $flag;
    }
    

    走到这一步,已经获取到了消息内容,即: 文本内容:$msgItem['MsgContent']['Text']

    图片地址:$msgItem['MsgContent']['ImageInfoArray'][0]['URL']

    接下来对消息内容发送审核请求并获取审核结果。

    Step 3 对消息内容进行审核,获取审核结果

    文本审核: https://cloud.tencent.com/document/product/460/56285

    图片审核: https://cloud.tencent.com/document/product/460/37318

    其他类型的审核可见页面左侧标签相关文档说明。

    关于审核,为了开发者更方便、更快速地使用数据万象的基础图片处理和媒体处理功能,以及 CDN 的云闪图片分发功能,我们提供了 SDK,开发者可根据具体需求进行选择,详情请参见对应的快速入门文档。对象存储的 SDK 也集成了数据万象的数据处理功能,若您需要使用其他语言的 SDK,例如 C++ 、JavaScript 等,请参见 COS SDK 概览。

    图片审核

    关于图片审核的图片限制说明,请参见 规则与限制。

    使用 COS PHP SDK 请求示例 ( sample/getObjectSensitiveContentRecognition.php ),IM 消息审核使用图片链接审核方式即可。

    <?php
    
    require dirname(__FILE__) . '/../vendor/autoload.php';
    
    $secretId = "SECRETID"; //"云 API 密钥 SecretId";
    $secretKey = "SECRETKEY"; //"云 API 密钥 SecretKey";
    $region = "ap-beijing"; //设置一个默认的存储桶地域
    $cosClient = new Qcloud\Cos\Client(
        array(
            'region' => $region,
            'schema' => 'https', //协议头部,默认为 http
            'credentials' => array(
                'secretId' => $secretId,
                'secretKey' => $secretKey)));
    try {
        //图片链接审核
        $imgUrl = 'https://test.jpg';
        $result = $cosClient->getObjectSensitiveContentRecognition(array(
            'Bucket' => 'examplebucket-125000000', //格式:BucketName-APPID
            'Key' => '/', // 链接图片资源路径写 / 即可
            'DetectType' => 'porn,ads',//可选四种参数:porn,politics,terrorist,ads,可使用多种规则,注意规则间不要加空格
            'DetectUrl' => $imgUrl,
    //      'Interval' => 5, // 审核 gif 时使用 截帧的间隔
    //      'MaxFrames' => 5, // 针对 GIF 动图审核的最大截帧数量,需大于 0 。
    //      'BizType' => '', // 审核策略
        ));
        // 请求成功
        print_r($result);
    } catch (\Exception $e) {
        // 请求失败
        echo($e);
    }
    

    响应结果:

    GuzzleHttp\Command\Result Object
    (
        [RequestId] => asdjahsfkjshfkjsdhfkjshfksjhfj=
        [PornInfo] => Array
            (
                [0] => Array
                    (
                        [Code] => 0
                        [Msg] => OK
                        [HitFlag] => 0
                        [Score] => 0
                        [Label] => 
                    )
    
            )
    
        [AdsInfo] => Array
            (
                [0] => Array
                    (
                        [Code] => 0
                        [Msg] => OK
                        [HitFlag] => 0
                        [Score] => 0
                        [Label] => 
                    )
    
            )
    
        [Key] => /
        [Bucket] => examplebucket-125000000
        [Location] => examplebucket-125000000.cos.ap-guangzhou.myqcloud.com//
    )
    

    文本审核

    使用 COS PHP SDK 请求示例 ( sample/detectText.php ),IM 消息审核使用文本内容审核方式即可。

    <?php
    
    require dirname(__FILE__) . '/../vendor/autoload.php';
    
    $secretId = "SECRETID"; //"云 API 密钥 SecretId";
    $secretKey = "SECRETKEY"; //"云 API 密钥 SecretKey";
    $region = "ap-beijing"; //设置一个默认的存储桶地域
    $cosClient = new Qcloud\Cos\Client(
        array(
            'region' => $region,
            'schema' => 'https', //协议头部,默认为 http
            'credentials'=> array(
                'secretId'  => $secretId ,
                'secretKey' => $secretKey)));
    try {
        // start --------------- 文本内容审核 ----------------- //
        $content = '敏感信息';
        $result = $cosClient->detectText(array(
            'Bucket' => 'examplebucket-125000000', //格式:BucketName-APPID
            'Input' => array(
                'Content' => base64_encode($content) // 文本需 base64_encode
            ),
            'Conf' => array(
                'DetectType' => 'Porn,Terrorism,Politics,Ads', //Porn,Terrorism,Politics,Ads,Illegal,Abuse 类型
                'BizType' => '',
            ),
        ));
        // 请求成功
        print_r($result);
        // end --------------- 文本内容审核 ----------------- //
    
    } catch (\Exception $e) {
        // 请求失败
        echo($e);
    }
    

    响应结果:

    GuzzleHttp\Command\Result Object
    (
        [RequestId] => asdjsajfaslofjsdofjsoifjsf=
        [ContentType] => application/xml
        [ContentLength] => 1237
        [JobsDetail] => Array
            (
                [Code] => Success
                [Message] => Array
                    (
                    )
    
                [JobId] => asjhdkjahfkjashfkjsdfhkjs
                [State] => Success
                [CreationTime] => 2021-09-09T20:04:05+08:00
                [Content] => 57qm54Ku
                [Result] => 1
                [SectionCount] => 1
                [PornInfo] => Array
                    (
                        [HitFlag] => 1
                        [Count] => 1
                    )
    
                [TerrorismInfo] => Array
                    (
                        [HitFlag] => 0
                        [Count] => 0
                    )
    
                [PoliticsInfo] => Array
                    (
                        [HitFlag] => 0
                        [Count] => 0
                    )
    
                [AdsInfo] => Array
                    (
                        [HitFlag] => 0
                        [Count] => 0
                    )
    
                [Section] => Array
                    (
                        [0] => Array
                            (
                                [StartByte] => 0
                                [PornInfo] => Array
                                    (
                                        [Code] => 0
                                        [HitFlag] => 1
                                        [Score] => 97
                                        [Keywords] => 敏感词
                                    )
    
                                [TerrorismInfo] => Array
                                    (
                                        [Code] => 0
                                        [HitFlag] => 0
                                        [Score] => 0
                                        [Keywords] => 
                                    )
    
                                [PoliticsInfo] => Array
                                    (
                                        [Code] => 0
                                        [HitFlag] => 0
                                        [Score] => 0
                                        [Keywords] => 
                                    )
    
                                [AdsInfo] => Array
                                    (
                                        [Code] => 0
                                        [HitFlag] => 0
                                        [Score] => 0
                                        [Keywords] => 
                                    )
    
                            )
    
                    )
    
            )
    
        [Bucket] => examplebucket-125000000
        [Location] => examplebucket-125000000.ci.ap-guangzhou.myqcloud.com/text/auditing
    )
    

    Step 4 回调请求返回结果

    走到这一步,说明已经对消息内容进行了审核并作出了是否违规的判断,接下来就是返回是否违规的结果即可。

    在 Step 1 回调应答示例中也提到了,ErrorCode=1 拒绝发言,ErrorCode=0 允许发言。

    HTTP/1.1 200 OK
    Server: nginx/1.7.10
    Date: Fri, 09 Oct 2015 02:59:55 GMT
    Content-Length: 75
    {
      "ActionStatus": "", 
      "ErrorInfo": "", 
      "ErrorCode": 0 // 1 为拒绝发言; 0 为允许发言
    }
    

    在用户侧效果为:

    具体参数及含义或其他应答方式可见 第三方回调简介 或同页面左侧其他文档页。

    至此,IM 发送消息、IM 请求回调、消息内容审核、回调应答、消息发送结果,所有步骤均已完成。

    四、写在最后

    随着各种网络安全法律法规和战略规划相继出台,监管部门对网络内容安全监管将日趋严格,对消息监管也日趋严格。对于聊天之间的消息如何把控也成为了重要的问题?对象存储本次推出的内容审核功能,可以帮助用户实现 IM 消息的审核服务,对于违规内容进行审核把控,为您的网络安全保驾护航。

    jerryjhou
        1
    jerryjhou  
       2021-10-03 18:34:12 +08:00 via Android
    人类迷惑行为之...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   971 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:19 · PVG 04:19 · LAX 12:19 · JFK 15:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.