uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶

uni-sec-check内容安全是unicloud封装了微信小程序的免费接口,文本内容安全识别(msgSecCheck)和音视频内容安全识别(mediaCheckAsync),如果我没选择使用uniapp+unicloud开发的话,可以轻松从插件市场引入uni-sec-check公共模块,完成内容安全检测,包含图片和文字检测,下面就针对文本内容和图片进行安全校验,前置知识肯定需要会uniapp和unicloud等知识。

官方文档使用手册

uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶_第1张图片

扫码体验,完整项目,如果二维码失效,小程序搜“鸡汤来喽”

文本内容安全校验

文本内容安全校验比较容易,只需要将编辑的内容发送给处理函数,接口将立即响应,返回处理结果,经过测试,一般会返回三种类型的敏感提示。

  • 如果涉及国家领导人将会返回(政治)
  • 如果涉及骂人及侮辱词汇返回(辱骂)
  • 如果涉及到色情相关词汇返回(色情),当我输入“啪啪啪”返回色情我就认了,输入“预约”也返回色情,审核有点太严了。
// 引入uni-sec-check公共模块
const UniSecCheck = require('uni-sec-check');
// 初始化实例
const uniSecCheck = new UniSecCheck({
	provider: 'mp-weixin',
	requestId: this.getUniCloudRequestId(), // 云函数内则写 context.requestId 云对象内则写 this.getUniCloudRequestId()
});
const checkRes = await uniSecCheck.textSecCheck({
	content: '', // 文本内容,不可超过500KB
	openid: '', // 用户的小程序openid
	scene: 2, // 场景值
	version: 2, // 接口版本号
});
console.log('checkRes: ', checkRes);

上面代码块是官方的示例,一般官方就给常规的演示,逻辑部分需要自己写,下面是我项目中封装的方法,给大家亮出代码来,也作为一个参考吧。

我将文本安全校验和图片安全校验,全部放到一个云对象中,这样方便统一管理,需要校验文字或者图片,只要调用对应的方法即可,云对象起名为“secCheckContent”。

// 引入uni-sec-check公共模块  
const UniSecCheck = require('uni-sec-check'); 
const db = uniCloud.database();
module.exports = {
    //文本安全校验方法textSecCheck({文本内容,openid,场景值,接口版本})
	async textSecCheck({content,openid="ozBCI62sKO1jZWxxH_nMoZQSYhHo",scene=2,version=2} = {}){		
		const uniSecCheck = new UniSecCheck({
			provider: 'mp-weixin',
			requestId: this.getUniCloudRequestId(), // 云函数内则写 context.requestId
		});	
		const checkRes = await uniSecCheck.textSecCheck({
			content,
			openid,
			scene,
			version
		})		
		if (checkRes.errCode === 'uni-sec-check-risk-content') {
			return {	
				code: 400,
				errMsg: '内容不合规',
				result: checkRes.result
			}
		}else if(checkRes.errCode){
			return {
				code: 400,
				errMsg: checkRes.errMsg,
				result: checkRes.result
			}
		}		
		return {
			errCode: 0,
			errMsg: ''
		};		
	}

在客户端调用云对象,引入textSecCheck方法,根据内容返回校验结果。

const secCheckObj = uniCloud.importObject("secCheckContent",{customUI:true});
let sec = await secCheckObj.textSecCheck({content:formData.value.content});	
if(sec.errCode != 0){
	uni.showModal({
		title:sec.errMsg,
		content:`输入的内容违规,涉及“${sec.result.label}”,请重新编辑!`,
		showCancel:false			
	})
	smtLoading.value = false;
	return;
}

以上就是关于文本内容安全的校验,是不是很简单,是不是以为图片校验也很容易,那就大错特错了,图片校验的难度比文本校验的难度高很多。

检测图片校验鉴黄

注意:
为什么说图片校验麻烦,是因为图片接口不能理解将校验结果返回,V2的检测结果是异步返回的,需要提前在微信公众平台「开发」-「开发设置」-「消息推送」开启消息服务,检测结果在 30 分钟内会推送到你的消息接收服务器,以下是全部步骤。

一、开通微信消息推送

1.「开发」-「开发设置」-「消息推送」点击启用

uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶_第2张图片

2.消息推送配置

uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶_第3张图片

3.生成URL服务器地址,系统将推送的消息返回到这个地址,接收到推送后处理你的逻辑

1) 创建一个名为secCheckMsg的云函数,单击右键上传并运行。

uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶_第4张图片

2)打开unicloud的web控制台,找到名为secCheckMsg的云函数,看一下运行后云函数是否跑通,点击右上角云函数详情。

uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶_第5张图片

3)设置云函数URL化的path部分,在域名后面添加一下和云函数名一样的路径即可“/secCheckMsg”

在这里插入图片描述

4) 复制以下代码到云函数,并重新单击右键“上传部署”
const crypto = require('crypto')
function getSignature (token, timestamp, nonce, msgEncrypt) {
	const str = [token, timestamp, nonce, msgEncrypt].sort().join('')
	return crypto.createHash('sha1').update(str).digest("hex")
}
function PKCS7Decode(buf) {
	let padSize = buf[buf.length - 1]
	return buf.slice(0, buf.length - padSize)
}
function decryptMsg (encodingAESKey, msgEncrypt) {
	const key = Buffer.from(encodingAESKey + '=', 'base64')
	const iv = key.slice(0, 16)		
	const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
	decipher.setAutoPadding(false)
	let deciphered = Buffer.concat([decipher.update(msgEncrypt, 'base64'), decipher.final()])
	deciphered = PKCS7Decode(deciphered)
	const content = deciphered.slice(16)
	const length = content.slice(0, 4).readUInt32BE(0)
	return {
		message: JSON.parse(content.slice(4, length + 4).toString()),
		appId: content.slice(length + 4).toString()
	}
}
exports.main = function(event, context) {
	const {
		signature: signature,
		timestamp: timestamp,
		nonce: nonce,
		echostr: echostr
	} = event.queryStringParameters
	const tmpStr = getSignature('你设置的Token令牌', timestamp, nonce)
	if (signature === tmpStr) {
		return echostr
	} else {
		return 
	}
}
5)点击提交,如果出现Token令牌校验不通过,说明云函数那里没有设置好,是不是直接将上面代码拷贝,没有修改下面的令牌为自己设置的Token。

uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶_第6张图片

6)如果出现下图配置已完成,说明消息推送的工作已经完成了。

uni-sec-check内容安全unicloud公共模块,校验微信小程序文本内容安全识别和图片智能鉴黄,uniapp进阶_第7张图片

二、在“secCheckContent”云对象中新增图片验证的方法“imgSecCheck”

/* imgSecCheck({对象})
*picurls    客户端传url数组来
*openid     用户openid
*scene      场景值
*version    版本号
*quanzi_id  业务ID
*/
async imgSecCheck({picurls,openid="ozBCI62sKO1jZWxxH_nMoZQSYhHo",scene=2,version = 2,quanzi_id}={}){		
	const uniSecCheck = new UniSecCheck({
		provider: 'mp-weixin',
		requestId: this.getUniCloudRequestId(), // 云函数内则写 context.requestId
	});
	//因为图片校验只能单图验证,所以将客户端传来的url数组循环遍历
	for (let image of picurls) {
		let res = await uniSecCheck.imgSecCheck({
			image,
			openid,
			scene,
			version
		})
		//将校验回调的唯一校验码traceId存储图片日志中
		await db.collection("sec-check-img-log").add({
			quanzi_id,
			picurl:image,
			traceId:res.traceId,
			state:0,
			publish_date:Date.now()
		})
	}	
}

三、客户端发布圈子首页将文章状态改为0(不可见),提示发布成功后,调用云对象的imgSecCheck进行校验。

let quanzi_id = res.id;
let picurls = formData.value.picurls.map(item=>item.url);			
if(picurls.length){
	await secCheckObj.imgSecCheck({picurls,quanzi_id});				
}	
uni.showToast({
	title:"发布成功,等待审核",
	icon:"none",
	mask:true
})		
uni.navigateBack();

四、在消息推送云函数中(secCheckMsg),将返回的结果进行判断,将违规图删除,没有违规的修改文章状态为可见。下面是我业务详细代码,作为参考。

const crypto = require('crypto');
function getSignature(token, timestamp, nonce, msgEncrypt) {
	const str = [token, timestamp, nonce, msgEncrypt].sort().join('')
	return crypto.createHash('sha1').update(str).digest("hex")
}
function PKCS7Decode(buf) {
	let padSize = buf[buf.length - 1]
	return buf.slice(0, buf.length - padSize)
}
function decryptMsg(encodingAESKey, msgEncrypt) {
	const key = Buffer.from(encodingAESKey + '=', 'base64')
	const iv = key.slice(0, 16)
	const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
	decipher.setAutoPadding(false)
	let deciphered = Buffer.concat([decipher.update(msgEncrypt, 'base64'), decipher.final()])
	deciphered = PKCS7Decode(deciphered)
	const content = deciphered.slice(16)
	const length = content.slice(0, 4).readUInt32BE(0)
	return {
		message: JSON.parse(content.slice(4, length + 4).toString()),
		appId: content.slice(length + 4).toString()
	}
}
exports.main = async function(event, context) {
	const db = uniCloud.database();
	const {
		signature: signature,
		timestamp: timestamp,
		nonce: nonce,
		echostr: echostr
	} = event.queryStringParameters	
	let body = ''
	if (event.body !== '') {
		body = JSON.parse(event.body)
	}
	let result = body	
	const tmpStr = getSignature('你自己设置的Token', timestamp, nonce)    
	if (signature === tmpStr) {
		// 验证是从微信发来的消息
		if (body.Encrypt) {
			const decrypt = decryptMsg('微信后台自动生成的秘钥', body.Encrypt);
			//返回的所有数据
			result = decrypt.message
			//根据图片校验返回的审核ID,比对图片日志表,获取满足条件的数据,作为后续增删改查的依据
			let imgLogs = await db.collection("sec-check-img-log").where({traceId:result.trace_id}).get();
			let quanzi_id = imgLogs.data[0].quanzi_id;		
			let picurl = imgLogs.data[0].picurl;
						
			//【重点】图片合规处理函数
			if (result.result.suggest == 'pass') {
				//根据图片日志返回的quanzi_id获取圈子表中对应指定的数据
				let res = await db.collection("soup_quanzi").where({
					_id:quanzi_id
				}).get();
				//修改图片状态,下面这段代码要是不想修改图片状态的话可以注释掉
				await db.collection("sec-check-img-log").where({traceId:result.trace_id}).update({state:1});
				//只用状态为0草稿箱的才能修改圈子状态,1通过的不再修改,-1不通过的也过滤掉
				if(res.data[0].quanzi_status==0){						
					await db.collection("soup_quanzi").where({
						_id:quanzi_id
					}).update({
						quanzi_status:1
					});		
				}					
			}
			
			//【重点】图片违规的处理函数
			if (result.result.suggest == 'risky') {
				//图片违规,立即将发布的圈子状态改为-1为审核不通过
				await db.collection("soup_quanzi").where({
					_id:quanzi_id
				}).update({
					quanzi_status:-1
				});
				//将图片日志的状态改为-1为不通过
				await db.collection("sec-check-img-log").where({traceId:result.trace_id}).update({state:-1});
				//删除违规图片,如果要看看用户传了什么,可以不删,但是占用存储空间,看个人选择,可以注释掉
				await uniCloud.deleteFile({fileList: [picurl]})				
			}
		}
		return 'success'
	} else {
		return 'success'
	}
}

图片校验完整的消息推送回调,下面代码给大家展示出来,分别是没有问题的图和违规图的返回值。

图片没有问题的返回值

{
    "result": {
        "ToUserName": "gh_ba616cbd6",
        "FromUserName": "ozBCI62MZ0HWGNeZ2ce7lSWq8",
        "CreateTime": 1695657534,
        "MsgType": "event",
        "Event": "wxa_media_check",
        "appid": "wxbd9d0a676b6a4",
        "trace_id": "651ae3a-5d4d44c-0f9e49e",
        "version": 2,
        "detail": [
            {
                "strategy": "content_model",
                "errcode": 0,
                "suggest": "pass",
                "label": 100,
                "prob": 90
            }
        ],
        "errcode": 0,
        "errmsg": "ok",
        "result": {
            "suggest": "pass",
            "label": 100
        }
    }
}

违规图的回调

{
    "result": {
        "ToUserName": "gh_4dbf781cf1",
        "FromUserName": "o7ZWr5bHxZ0yMEt6-k_8RUU",
        "CreateTime": 1693843523,
        "MsgType": "event",
        "Event": "wxa_media_check",
        "appid": "wx3f7cf3d3a423a",
        "trace_id": "64f603b-4a8bf26-05c372e",
        "version": 2,
        "detail": [
            {
                "strategy": "content_model",
                "errcode": 0,
                "suggest": "risky",
                "label": 20002,
                "prob": 90
            }
        ],
        "errcode": 0,
        "errmsg": "ok",
        "result": {
            "suggest": "risky",
            "label": 20002
        }
    }
}

你可能感兴趣的:(uniapp+uniCloud,安全,微信小程序,uni-app)