文章目录
之前有开发一个微信小程序,拥有图片上传的功能,上线运行后一直表现良好,用户渐渐增多。
但突然有一天,收到一个系统消息:提示我小程序存在内容安全风险,缺乏对不法违规内容的过滤机制,需要整改,消息如下图:

该消息是安全风险警告,需要限期内进行整改调整,否则就会禁用小程序的一些功能,比如不能被搜索、不能通过二维码打开小程序、不能分享小程序内容、不能跳转其他小程序等等。
鉴于此,小程序不进行修改肯定是不行的,否则相关功能将不可用,搜索流量消失,影响实在有点大。
在进行修改前还得先了解下微信小程序的内容审核的具体情况,根据信息提示里的链接,直接查看。
在微信小程序平台运营规范-行为规范-内容安全部分,提到了以下内容:
小程序涉及未设置过滤违法、违规等不当信息内容的机制。
必须调用内容安全检测接口校验文本/图片是否含有敏感内容,提升信息安全防护能力,降低被恶意利用导致传播恶意内容的风险。
针对内容安全,目前主要是文本输入和图片上传,需要进行内容安全的检测。
主要针对输入文本或上传的图片中存在的色情、时政违规、暴恐等有害内容,需要进行内容审核,过滤敏感信息,确保输入内容是安全的。
而在实际开发中,我们可以使用微信小程序提供的开放接口,对这两块内容进行基本的安全检测:

如上图所示,就是微信小程序提供的文本检测接口和音频图片检测接口,基于智能AI程序进行判断。其中图片检测还可以使用另外一个接口:imgSecCheck 专门用于检测一张图片是否违法违规。
以上接口都有多种调用方式,包括https服务、云调用以及第三方调用,本文将重点介绍云调用的方式,在此之前,我们需要先了解小程序云函数。
微信提供了云开发功能,在小程序中,我们也可以方便的建立云开发服务,协助我们快速的进行功能开发,避免搭建服务器。具体的微信云开发介绍,可以查看微信小程序开发文档。
如果要在小程序中使用云服务,则我们创建小程序的时候,选择开启微信云服务,即可:

需要明确的一点是,微信提供的云服务是需要收费的,目前有1个月的试用期,可以使用。

本文的重点并不是如何搭建微信小程序云开发服务,而是针对内容安全的检测处理,所以不再一一介绍云开发这块的内容,网上有各种教程,大家可自行搜索。
针对内容安全检测,我们使用云调用的时候,可以使用云函数,前提是已经搭建好云开发服务。
关于图片的检测,使用云函数,接口方法是:openapi.security.imgSecCheck。
首先,配置代码权限,在已开启云服务的小程序项目中,会存在一个 cloudfunctions 云目录,可以右键单击,创建云函数:

上图所示,点击 新建Node.js云函数,就能够创建自己的云函数。
比如,我们创建一个名为 checkImageSec 的云函数,用来处理图片检测,则在 cloudfunctions 云目录下会新建一个名为 checkImageSec 的文件夹,并且有自动创建三个文件:

如上图所示,文件自动创建,这里需要注意的是,在 config.json 文件中,我们得配置 openapi.security.imgSecCheck 接口权限,否则无法调用。
这里的云函数本质上是一个 Node 服务,所以开发环境电脑中必须先安装 Node.js,云函数默认依赖一个微信提供的包:wx-server-sdk,用于创建云对象。
我们可以在 index.js 文件中编写所需的图片检测代码,调用 openapi.security.imgSecCheck 接口,基本实现如下:
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
// 云函数入口函数
exports.main = async (event) => {
const arrayBuffer = event.arrayBuffer
const contentType = event.contentType
const buf = Buffer.from(arrayBuffer)
const result = await cloud.openapi.security.imgSecCheck({
media: {
contentType,
value: buf
}
})
return result
}
以上代码,初始化 cloud 云对象,在入口函数中,通过参数接收图片信息,
ArrayBuffer 格式二进制数据,在Nodejs中转为 Buffer 数据设置好以后,就创建好了云函数checkImageSec, 小程序前端就能调用它对图片进行检测了。
在调用云函数之前,我们先实现小程序的图片上传功能。
小程序中图片上传比较简单,直接使用文档提供的接口 chooseMedia,用于选择媒体文件(图片或视频):
wx.chooseMedia({
count,
mediaType: ['image'],
sizeType: [ 'original' ],
sourceType: [ 'album' ],
success: (imgRes) => {
callBack && callBack(imgRes)
},
fail: () => {}
})
以上代码,从手机相册选择图片上传,将获取到图片的临时目录地址 tempFilePath。
当前图片来自于相册原始图片,如果尺寸较大或者格式不对(如webp格式图片等),就并不符合我们的需求,因为图片安全检测接口 imgSecCheck 对图片尺寸和格式有要求:
要检测的图片文件,格式支持PNG、JPEG、JPG、GIF,图片尺寸不超过 750px x 1334px
所以,我们还需要对接收到的大尺寸图片进行尽量小的压缩。
通过前端,在小程序中进行图片压缩,能使用的当然就是canvas了,我们先通过 getImageInfo 接口获取图片的宽高信息:
wx.getImageInfo({
src: tempFilePath,
success: async (imgInfo) => {
try {
callBack && callBack(imgInfo)
}
},
fail: () => {}
})
以上代码,获取到图片的信息 imgInfo,将包含图片本地路径、宽度、高度以及各式信息等,而我们缩小图片必须使用到宽高数据。
缩小图片,我们创建一个canvas元素(id为checkCanvas),获取对应的上下文对象,并设置图片宽高最大不能超过120,代码如下:
const SIZE = 120
const ratio = Math.max(imgInfo.width / SIZE, imgInfo.height / SIZE, 1)
const smallWidth = Math.trunc(imgInfo.width / ratio)
const smallHeight = Math.trunc(imgInfo.height / ratio)
// 将宽高大小设置到页面的canvas元素(checkCanvas)上
this.smallWidth = smallWidth
this.smallHeight = smallHeight
const ctx = wx.createCanvasContext('checkCanvas')
ctx.drawImage(imgInfo.path, 0, 0, smallWidth, smallHeight)
ctx.draw(false, function () {
setTimeout(() => {
wx.canvasToTempFilePath({
canvasId: 'checkCanvas',
width: smallWidth,
height: smallHeight,
destWidth: smallWidth,
destHeight: smallHeight,
success: (res) => {
resolve(res.tempFilePath)
},
fail: (e) => {
reject(e)
}
})
}, 100)
})
图片缩小到120以内后,通过小程序的canvas转换接口 wx.canvasToTempFilePath 生成了新的临时图片文件,我们接下来就可以对它进行安全检测了。
上面在编写云函数的 Node.js 代码时,提到了图片参数需要使用 Buffer 数据,前端图片数据应为 ArrayBuffer 格式的数据。
图片临时文件,可以通过微信小程序提供的文件读取接口,获取对应的 ArrayBuffer 格式数据:
const fsManager = wx.getFileSystemManager()
const bufferData = fsManager.readFileSync(imgFilePath)
readFileSync 接口会默认以 ArrayBuffer 格式读取文件的二进制内容,这样我们就得到了图片文件的可用格式数据。
接着,我们就可以调用云函数,进行检测处理,调用方式也比较简单:
wx.cloud.callFunction({
name: 'checkImageSec',
data: {
contentType: `image/png`,
arrayBuffer: bufferData
},
success: (res) => {
if (res.result.errCode === 0) {
console.log('合法图片' )
} else if (res.result.errCode === 87014) {
console.log('违法图片')
}
console.log('其他异常')
},
fail: () => {
console.log('检测失败')
}
})
至此,我们调用云函数,进行图片内容安全检测的基本代码都完成了,通过这种方法,能够初步检测图片是否合规,禁止违规图片上传并显示出来。
文本检测调用云开放接口:openapi.security.msgSecCheck,整个调用的流程和图片检测基本一致,只不过因为数据内容的不同,在数据处理和参数传递上有一些区别。
在云函数部分(Nodejs代码),需要传入 openid,通过获取微信上下文对象(cloud.getWXContext()),可以得到openid,我们创建名为 checkTextSec 的云函数,核心代码如下:
exports.main = async (event) => {
const wxContext = cloud.getWXContext()
const openid = wxContext.OPENID
const content = event.content
const result = await cloud.openapi.security.msgSecCheck({
openid,
scene: 1,
version: 2,
content
})
}
这里参数直接使用文本内容,即字符串,我们在小程序前端部分调用云函数 checkTextSec,传入文本框的输入内容,对文本审核检测。
// content 输入框文本内容
wx.cloud.callFunction({
name: 'checkTextSec',
data: { content },
success: (res) => {
if (res.result.errCode === 0) {
if (res.result.result.label === 100) {
console.log('合法文本')
} else {
console.log('违法文本')
}
} else {
console.log('其他异常')
}
},
fail: () => {
console.log('处理失败')
}
})
以上代码就是调用云函数处理文本内容的安全检测,与图片检测基本类似。
虽然,我们已经使用了微信小程序提供的开放服务,进行了图片和文本的内容安全检测,但是并不能完全解决问题,微信小程序开发者文档里已有提醒:

这里建议开发者最好进行人工审核,以弥补AI智能审核的不足。
而要想进行人工审核,必然需要上传用户的图片和输入文本,通过后台审核干预的情形进行处理。这个成本可以说是很大的,很多小程序做不到。
所以,当我们的小程序因为内容安全被封禁以后,在找微信客服人员进行申诉时,如果微信客服人员死扣人工审核的话,对于个人开发者来说这个小程序基本上就算玩完,可以直接弃用。

因为申诉失败的概率实在太大了!
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s
我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?
我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,