-

微信小程序的许多业务场景需要通过UGC(用户产生内容)的方式,比如昵称/花名、个人资料签名/日志/聊天/评论、头像/表情/相片、直播等各种场景,其格式内容包括但不限于短文本、长内容、图片或视频等来实现更好的用户体验或更丰富的内容功能和服务场景。但是如果这类功能的使用如果没有做好对用户发布内容的安全审查,可能会产生政治有害等违法违规的内容。一旦被利用进行传播,对小程序用户带来有损的体验,小程序开发者也可能因此承担平台或法律的追责及处罚。因此包含UGC功能的小程序都需要有内容安全检测。

一、文字内容安全

使用开发者工具新建一个云函数,如msgsec,然后在config.json里添加security.msgSecCheck云调用的权限,使用npm install安装依赖之后,上传并部署所有文件(此时也会更新权限)。

{
  "permissions": {
    "openapi": [
      "security.imgSecCheck",
      "security.msgSecCheck"
    ]
  }
}

然后再在index.js里输入以下代码,

const cloud = require('wx-server-sdk')
cloud.init({
    env: cloud.DYNAMIC_CURRENT_ENV
  })
exports.main = async (event, context) => {
    try {
        const result = await cloud.openapi.security.msgSecCheck({
            content:`特3456书yuuo莞6543李zxcz蒜7782法fgnv级
            完2347全dfji试3726测asad感3847知qwez到`
        })
        return result
    } catch (error) {
        return error
    }
}

调用该云函数,接口errcode返回87014(内容含有违法违规内容):

errMsg: "cloud.callFunction:ok", 
result: {
    errCode: 87014
    errMsg: "openapi.security.msgSecCheck:fail risky content hint: [bgh98a06644711]"}

而如果返回的result.errCode的值为0,说明内容正常。

errMsg: "cloud.callFunction:ok"
result: {
    errMsg: "openapi.security.msgSecCheck:ok",
    errCode: 0}

二、图片鉴黄

图片内容安全检测和文字内容安全检测最大的不同在于,我们需要考虑图片传输的耗时以及检测的图片不能大于1M这样的一个限制,当图片尺寸比较大时,我们需要对图片进行压缩处理。而且要检测的图片文件的格式为PNG、JPEG、JPG、GIF,图片尺寸不超过 750px x 1334px。通常情况下我们使用小程序端chooseImage上传图片时,我们尽量要求使用compressed压缩图,相册的压缩图一般都不会超过1M。

  • 如果图片比较小(大约200k以内),我们可以直接把图片存储到云存储里,然后在云函数里下载该图片进行图片安全检测;

  • 如果图片比较大(比如大于100k,小于1M),我们可以把图片存储到云存储之后,在云函数端下载该图片,使用前面所说的Sharp模块,对图片进行压缩处理,然后进行图片安全检测。

  • 如果图片大于1M,那图片的压缩就不建议在云函数端处理,要在小程序端使用Canvas进行压缩,然后再传输到云函数端进行安全检测。

const cloud = require('wx-server-sdk')
cloud.init({
    env: cloud.DYNAMIC_CURRENT_ENV
  })
exports.main = async (event, context) => {
  const fileID = 'cloud://xly-xrlur.786c-xly-xrlur-1300446086/1572315793628-366.png'
  const res = await cloud.downloadFile({
    fileID: fileID,
  })
  const Buffer = res.fileContent
  try {
    const result = await cloud.openapi.security.imgSecCheck({
      media: {
        contentType: 'image/png',
        value: Buffer
      }
    })
    return result
   } catch (error) {
    return error
  }
}

三、图像内容安全拓展能力

云调用在图像内容安全处理方面,功能有一些不足的地方(比如没有细分涉黄、涉政、涉暴恐以及广告引导类),在限制上有一点严格(对图片的大小有严格的要求),建议大家安装云开发图像安全审核的拓展能力。

它的安装方式在云调用与拓展能力章节有介绍,而使用方式上一节图像处理的拓展能力是一脉相承的,有着相同的使用方法,这是因为图像内容安全就是图像处理的一部分。所以要使用图像内容安全拓展能力建议先阅读之前的内容,这里只给出实际的代码。

1、在小程序端使用图像安全审核

首先我们参考上一节内容构建图像处理的npm,然后再在imgprocess.js里引入包以及在Page函数里写一个事件处理函数。图像安全审核只能后置校验,也就是只能对已经上传到云存储的图片进行内容安全审核,方法如下:

const extCi = require("./../../miniprogram_npm/@cloudbase/extension-ci-wxmp");
Page({
  async imgSec(){
    extCi.invoke({
      action: "DetectType",
      cloudPath: "tcbdemo.jpg", 
      operations: {
        type: 'porn,ads,terrorist,politics'
      }
    }).then(res => {
        console.log(res.data);
    }).catch(err => {
        console.log(err);
    })
  }
})

这里的type为内容审核的类型,porn(涉黄识别)、terrorist(涉暴恐识别)、politics(涉政识别)、ads(广告识别),我们可以像上面四个一起写,也可以只写其中的几个,用逗号,隔开即可。

打印res.data,内有RecognitionResult的对象,会显示图片内容审核的结果,下面显示带有商业广告:

  • HitFlag,表示是否命中:0(未命中),1(命中),2(疑似);

  • Score,审核分值:0 - 60分(正常),60 - 90分(疑似敏感),90 - 100分(确定敏感)

  • Label,为识别的标签

RecognitionResult{
  PornInfo: {Code: 0, Msg: "OK", HitFlag: 0, Score: 14, Label: ""}
  TerroristInfo: {Code: 0, Msg: "OK", HitFlag: 0, Score: 0, Label: ""}
  PoliticsInfo: {Code: 0, Msg: "OK", HitFlag: 0, Score: 26, Label: ""}
  AdsInfo: {Code: 0, Msg: "OK", HitFlag: 1, Score: 98, Label: "淘宝"}
}

在小程序端审核图片,我们可以先上传图片到云存储,然后获取图片在云存储的cloudPath(不是fileID,是相对云存储的绝对路径),再对图片进行审核,审核成功才予以显示,审核失败就删除该图片,让用户重新上传。

2、在云函数端使用图像安全审核

使用开发者工具新建一个imgSec的云函数,然后在package.json里添加latest最新版的@cloudbase/extension-ci,并右键云函数目录选择在终端中打开输入命令npm install安装依赖:

"dependencies": {
  "wx-server-sdk": "latest",
  "@cloudbase/extension-ci": "latest"
}

然后再在index.js里输入以下代码,代码的具体含义可以参考小程序端的内容讲解:

const cloud = require('wx-server-sdk')
cloud.init({
    env: cloud.DYNAMIC_CURRENT_ENV
  })
const extCi = require('@cloudbase/extension-ci')
cloud.registerExtension(extCi)
async function imgSec() {
  try {
    const res = await app.invokeExtension('CloudInfinite', {
      action: 'DetectType',
      cloudPath: 'tcbdemo.png', 
      operations: {
        type: 'porn,ads,terrorist,politics'
      }
    })
    console.log(res)
    return res
  } catch (err) {
    console.log(err)
  }
}