uni-sec-check內(nèi)容安全是unicloud封裝了微信小程序的免費(fèi)接口,文本內(nèi)容安全識(shí)別(msgSecCheck)和音視頻內(nèi)容安全識(shí)別(mediaCheckAsync),如果我沒選擇使用uniapp+unicloud開發(fā)的話,可以輕松從插件市場(chǎng)引入uni-sec-check公共模塊,完成內(nèi)容安全檢測(cè),包含圖片和文字檢測(cè),下面就針對(duì)文本內(nèi)容和圖片進(jìn)行安全校驗(yàn),前置知識(shí)肯定需要會(huì)uniapp和unicloud等知識(shí)。
官方文檔使用手冊(cè)
掃碼體驗(yàn),完整項(xiàng)目,如果二維碼失效,小程序搜“雞湯來(lái)嘍”
文本內(nèi)容安全校驗(yàn)
文本內(nèi)容安全校驗(yàn)比較容易,只需要將編輯的內(nèi)容發(fā)送給處理函數(shù),接口將立即響應(yīng),返回處理結(jié)果,經(jīng)過測(cè)試,一般會(huì)返回三種類型的敏感提示。
- 如果涉及國(guó)家領(lǐng)導(dǎo)人將會(huì)返回(政治)
- 如果涉及罵人及侮辱詞匯返回(辱罵)
- 如果涉及到色情相關(guān)詞匯返回(色情),當(dāng)我輸入“啪啪啪”返回色情我就認(rèn)了,輸入“預(yù)約”也返回色情,審核有點(diǎn)太嚴(yán)了。
// 引入uni-sec-check公共模塊
const UniSecCheck = require('uni-sec-check');
// 初始化實(shí)例
const uniSecCheck = new UniSecCheck({
provider: 'mp-weixin',
requestId: this.getUniCloudRequestId(), // 云函數(shù)內(nèi)則寫 context.requestId 云對(duì)象內(nèi)則寫 this.getUniCloudRequestId()
});
const checkRes = await uniSecCheck.textSecCheck({
content: '', // 文本內(nèi)容,不可超過500KB
openid: '', // 用戶的小程序openid
scene: 2, // 場(chǎng)景值
version: 2, // 接口版本號(hào)
});
console.log('checkRes: ', checkRes);
上面代碼塊是官方的示例,一般官方就給常規(guī)的演示,邏輯部分需要自己寫,下面是我項(xiàng)目中封裝的方法,給大家亮出代碼來(lái),也作為一個(gè)參考吧。
我將文本安全校驗(yàn)和圖片安全校驗(yàn),全部放到一個(gè)云對(duì)象中,這樣方便統(tǒng)一管理,需要校驗(yàn)文字或者圖片,只要調(diào)用對(duì)應(yīng)的方法即可,云對(duì)象起名為“secCheckContent”。
// 引入uni-sec-check公共模塊
const UniSecCheck = require('uni-sec-check');
const db = uniCloud.database();
module.exports = {
//文本安全校驗(yàn)方法textSecCheck({文本內(nèi)容,openid,場(chǎng)景值,接口版本})
async textSecCheck({content,openid="ozBCI62sKO1jZWxxH_nMoZQSYhHo",scene=2,version=2} = {}){
const uniSecCheck = new UniSecCheck({
provider: 'mp-weixin',
requestId: this.getUniCloudRequestId(), // 云函數(shù)內(nèi)則寫 context.requestId
});
const checkRes = await uniSecCheck.textSecCheck({
content,
openid,
scene,
version
})
if (checkRes.errCode === 'uni-sec-check-risk-content') {
return {
code: 400,
errMsg: '內(nèi)容不合規(guī)',
result: checkRes.result
}
}else if(checkRes.errCode){
return {
code: 400,
errMsg: checkRes.errMsg,
result: checkRes.result
}
}
return {
errCode: 0,
errMsg: ''
};
}
在客戶端調(diào)用云對(duì)象,引入textSecCheck方法,根據(jù)內(nèi)容返回校驗(yàn)結(jié)果。
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:`輸入的內(nèi)容違規(guī),涉及“${sec.result.label}”,請(qǐng)重新編輯!`,
showCancel:false
})
smtLoading.value = false;
return;
}
以上就是關(guān)于文本內(nèi)容安全的校驗(yàn),是不是很簡(jiǎn)單,是不是以為圖片校驗(yàn)也很容易,那就大錯(cuò)特錯(cuò)了,圖片校驗(yàn)的難度比文本校驗(yàn)的難度高很多。
檢測(cè)圖片校驗(yàn)鑒黃
注意:
為什么說圖片校驗(yàn)麻煩,是因?yàn)閳D片接口不能理解將校驗(yàn)結(jié)果返回,V2的檢測(cè)結(jié)果是異步返回的,需要提前在微信公眾平臺(tái)「開發(fā)」-「開發(fā)設(shè)置」-「消息推送」開啟消息服務(wù),檢測(cè)結(jié)果在 30 分鐘內(nèi)會(huì)推送到你的消息接收服務(wù)器,以下是全部步驟。
一、開通微信消息推送
1.「開發(fā)」-「開發(fā)設(shè)置」-「消息推送」點(diǎn)擊啟用
2.消息推送配置
3.生成URL服務(wù)器地址,系統(tǒng)將推送的消息返回到這個(gè)地址,接收到推送后處理你的邏輯
1) 創(chuàng)建一個(gè)名為secCheckMsg的云函數(shù),單擊右鍵上傳并運(yùn)行。
2)打開unicloud的web控制臺(tái),找到名為secCheckMsg的云函數(shù),看一下運(yùn)行后云函數(shù)是否跑通,點(diǎn)擊右上角云函數(shù)詳情。
3)設(shè)置云函數(shù)URL化的path部分,在域名后面添加一下和云函數(shù)名一樣的路徑即可“/secCheckMsg”
4) 復(fù)制以下代碼到云函數(shù),并重新單擊右鍵“上傳部署”
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('你設(shè)置的Token令牌', timestamp, nonce)
if (signature === tmpStr) {
return echostr
} else {
return
}
}
5)點(diǎn)擊提交,如果出現(xiàn)Token令牌校驗(yàn)不通過,說明云函數(shù)那里沒有設(shè)置好,是不是直接將上面代碼拷貝,沒有修改下面的令牌為自己設(shè)置的Token。
6)如果出現(xiàn)下圖配置已完成,說明消息推送的工作已經(jīng)完成了。
二、在“secCheckContent”云對(duì)象中新增圖片驗(yàn)證的方法“imgSecCheck”
/* imgSecCheck({對(duì)象})
*picurls 客戶端傳url數(shù)組來(lái)
*openid 用戶openid
*scene 場(chǎng)景值
*version 版本號(hào)
*quanzi_id 業(yè)務(wù)ID
*/
async imgSecCheck({picurls,openid="ozBCI62sKO1jZWxxH_nMoZQSYhHo",scene=2,version = 2,quanzi_id}={}){
const uniSecCheck = new UniSecCheck({
provider: 'mp-weixin',
requestId: this.getUniCloudRequestId(), // 云函數(shù)內(nèi)則寫 context.requestId
});
//因?yàn)閳D片校驗(yàn)只能單圖驗(yàn)證,所以將客戶端傳來(lái)的url數(shù)組循環(huán)遍歷
for (let image of picurls) {
let res = await uniSecCheck.imgSecCheck({
image,
openid,
scene,
version
})
//將校驗(yàn)回調(diào)的唯一校驗(yàn)碼traceId存儲(chǔ)圖片日志中
await db.collection("sec-check-img-log").add({
quanzi_id,
picurl:image,
traceId:res.traceId,
state:0,
publish_date:Date.now()
})
}
}
三、客戶端發(fā)布圈子首頁(yè)將文章狀態(tài)改為0(不可見),提示發(fā)布成功后,調(diào)用云對(duì)象的imgSecCheck進(jìn)行校驗(yàn)。
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:"發(fā)布成功,等待審核",
icon:"none",
mask:true
})
uni.navigateBack();
四、在消息推送云函數(shù)中(secCheckMsg),將返回的結(jié)果進(jìn)行判斷,將違規(guī)圖刪除,沒有違規(guī)的修改文章狀態(tài)為可見。下面是我業(yè)務(wù)詳細(xì)代碼,作為參考。
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('你自己設(shè)置的Token', timestamp, nonce)
if (signature === tmpStr) {
// 驗(yàn)證是從微信發(fā)來(lái)的消息
if (body.Encrypt) {
const decrypt = decryptMsg('微信后臺(tái)自動(dòng)生成的秘鑰', body.Encrypt);
//返回的所有數(shù)據(jù)
result = decrypt.message
//根據(jù)圖片校驗(yàn)返回的審核ID,比對(duì)圖片日志表,獲取滿足條件的數(shù)據(jù),作為后續(xù)增刪改查的依據(jù)
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;
//【重點(diǎn)】圖片合規(guī)處理函數(shù)
if (result.result.suggest == 'pass') {
//根據(jù)圖片日志返回的quanzi_id獲取圈子表中對(duì)應(yīng)指定的數(shù)據(jù)
let res = await db.collection("soup_quanzi").where({
_id:quanzi_id
}).get();
//修改圖片狀態(tài),下面這段代碼要是不想修改圖片狀態(tài)的話可以注釋掉
await db.collection("sec-check-img-log").where({traceId:result.trace_id}).update({state:1});
//只用狀態(tài)為0草稿箱的才能修改圈子狀態(tài),1通過的不再修改,-1不通過的也過濾掉
if(res.data[0].quanzi_status==0){
await db.collection("soup_quanzi").where({
_id:quanzi_id
}).update({
quanzi_status:1
});
}
}
//【重點(diǎn)】圖片違規(guī)的處理函數(shù)
if (result.result.suggest == 'risky') {
//圖片違規(guī),立即將發(fā)布的圈子狀態(tài)改為-1為審核不通過
await db.collection("soup_quanzi").where({
_id:quanzi_id
}).update({
quanzi_status:-1
});
//將圖片日志的狀態(tài)改為-1為不通過
await db.collection("sec-check-img-log").where({traceId:result.trace_id}).update({state:-1});
//刪除違規(guī)圖片,如果要看看用戶傳了什么,可以不刪,但是占用存儲(chǔ)空間,看個(gè)人選擇,可以注釋掉
await uniCloud.deleteFile({fileList: [picurl]})
}
}
return 'success'
} else {
return 'success'
}
}
圖片校驗(yàn)完整的消息推送回調(diào),下面代碼給大家展示出來(lái),分別是沒有問題的圖和違規(guī)圖的返回值。
圖片沒有問題的返回值文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-758599.html
{
"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
}
}
}
違規(guī)圖的回調(diào)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-758599.html
{
"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
}
}
}
到了這里,關(guān)于uni-sec-check內(nèi)容安全unicloud公共模塊,校驗(yàn)微信小程序文本內(nèi)容安全識(shí)別和圖片智能鑒黃,uniapp進(jìn)階的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!