內(nèi)容安全檢測,是每一個小程序主都面臨的“頭疼”問題,輕則短暫性不可訪問,重則永久封號,甚至關(guān)小黑屋。本文將為您詳細(xì)說明,如何在小程序中對一段文本進(jìn)行合法內(nèi)容檢測,以判斷是否含有違法違規(guī)內(nèi)容。
本文重點為你講述:
內(nèi)容安全檢測常見應(yīng)用場景及解決辦法
學(xué)會使用小程序·云開發(fā)的云函數(shù)+結(jié)合request-promise第三方庫實現(xiàn)內(nèi)容請求校驗
掌握如何在小程序端請求云函數(shù)(有別于傳統(tǒng)的wx.request的方式(類似AJax))
在云開發(fā)的云函數(shù)端,利用第三方https請求庫(request,request-promise),獲取Access_token,以及向微信官方提供的內(nèi)容檢測接口發(fā)請求進(jìn)行校驗
云函數(shù)端與小程序端錯誤碼的處理
無論是小程序還是自行開發(fā)的一些類似社交,帶有用戶自行產(chǎn)生內(nèi)容的軟件應(yīng)用,例如:即時通訊,社群,論壇,音視頻直播等,對于接入內(nèi)容安全的檢測是非常有必要的。
對于小程序而言,這一點在審核上是非常嚴(yán)格的,凈化言行,做一個知法守法的人很重要...
接入內(nèi)容安全檢測,規(guī)避輸入一些違法違規(guī)低俗等內(nèi)容,避免辛辛苦苦開發(fā)出來的應(yīng)用。
被惡意上傳反動言論或上傳一些違規(guī)內(nèi)容(文字/圖片/視頻等),導(dǎo)致小程序或應(yīng)用被下架,或遭永久禁封,或個人及公司被公安機(jī)關(guān)打電話,約喝茶等,這樣的話,就得不償失了的。
每一種方法各有優(yōu)劣勢,具體如下圖。
解決方案 | 優(yōu)勢 | 劣勢 | |
---|---|---|---|
1 | 引入第三方接口對內(nèi)容進(jìn)行校驗 | 前端同學(xué)只需按照官方提供的第三方接口文檔,進(jìn)行校驗即可,無需后臺介入,功能強(qiáng)大,覆蓋范圍廣 | 接口調(diào)用的頻次有限制,收費 |
2 | 公司后臺小伙伴自行開發(fā)文本,圖片,音視頻等內(nèi)容審核接口 | 后臺小伙伴自己造輪子,根據(jù)自己的業(yè)務(wù)需求以及用戶屬性,自定義內(nèi)容審核機(jī)制 | 開發(fā)周期長,成本大,難以覆蓋全面 |
3 | 調(diào)用小程序服務(wù)端提供的內(nèi)容安全API進(jìn)行校驗 | 簡單,高效 | 想不出來,因為相比前兩種方案,對于不依賴后端接口的開發(fā)者來說,簡直是雪中送炭 |
服務(wù)器開發(fā)模式,相信大家都相對比較熟悉,在此就不再贅述。接下來為大家重點介紹,如何通過小程序·云開發(fā)的云函數(shù)實現(xiàn)內(nèi)容安全檢測。
Step 1: 在小程序端先布局:完成靜態(tài)頁面。(pages文件夾下的文件都是屬于小程序前端代碼,每個文件夾目錄代表的就是一個模塊,一個頁面)
小程序前端wxml代碼示例
<view class="container">
<textarea class="content" placeholder="寫點文字..." bindinput="onInput" auto-focus bindfocus="onFocus" bindblur="onBlur">
</textarea>
</view>
<view class="footer">
<button class="send-btn" size="default" bind:tap="send">發(fā)布</button>
</view>
小程序前端wxss代碼示例
/* pages/msgSecCheck/msgSecCheck.wxss */
.container {
padding: 20rpx;
}
.content {
width: 100%;
height: 360rpx;
box-sizing: border-box;
font-size: 32rpx;
border: 1px solid #ccc;
}
.footer {
width: 100%;
height: 80rpx;
line-height: 80rpx;
position: fixed;
bottom: 0;
box-sizing: border-box;
background: #34bfa3;
}
.send-btn {
width: 100% !important;
color: #fff;
font-size: 32rpx;
}
button {
width: 100%;
background: #34bfa3;
border-radius: 0rpx;
}
button::after {
border-radius: 0rpx !important;
}
經(jīng)過wxml與wxss的編寫后,UI最終長成這樣
小程序端邏輯JS代碼示例
// pages/msgSecCheck/msgSecCheck.js
Page({
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
textareaVal: '' // 頁面中需要顯示的數(shù)據(jù),初始化定義在data下面
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載
*/
onLoad: function (options) {
},
// 監(jiān)聽表單時,數(shù)據(jù)有變化時
onInput(event) {
let textVal = event.detail.value;
this.setData({
textareaVal: textVal
})
},
// 聚焦焦點時
onFocus() {
console.log('聚焦焦點時');
},
// 失去焦點時
onBlur(event) {
console.log("失去焦點時");
// 前端可進(jìn)行手動的弱校驗,也可以在失去焦點時發(fā)送請求進(jìn)行文本的校驗,但是每次失去焦點就請求一次,這樣是消耗云資源的,在發(fā)布時候與失去焦點做校驗兩者都可以
},
// 發(fā)布
send() {
console.log("觸發(fā)發(fā)布按鈕")
wx.cloud.callFunction({ // 請求msgSecCheck1云函數(shù)
name: 'msgSecCheck1',
data: {
content: this.data.textareaVal // 需要向云函數(shù)msgSecCheck1傳入的值
}
}).then(res => { // 成功時的響應(yīng)返回結(jié)果
console.log(res);
}).catch(err => { // 失敗時,返回的結(jié)果
console.error(err);
})
}
})
Step 3 :服務(wù)端邏輯處理。在小程序云函數(shù)端創(chuàng)建云函數(shù)msgSecCheck1,這個名字你可以自定義,與小程序前端請求的名字保持一致就可以了。
選中云函數(shù),右鍵并打開命令行終端安裝request,request-promise,因為request-promise依賴于request,兩個都要安裝,最后一鍵上傳部署就可以了
npm install request
npm install request-promise
如果遇到在小程序端請求云函數(shù)時,遇到類似下面的錯誤,找不到什么xxx模塊之類的 先看錯誤碼,然后在官方文檔中找到該錯誤碼代表的含義
一看錯誤,沒有找到模塊,在云函數(shù)的目錄下的package.json中查看是否有安裝錯誤中提示的包的,要是沒有的話,就安裝一下就可以了的,同時記得每次更改后都要上傳部署一下,也可以選擇云函數(shù)中文件的增量上傳
對于小程序開發(fā),其實與web端開發(fā)也是類似,給元素綁定事件,然后獲取元素,只是小程序端沒有DOM,BOM的那一套東西,它是數(shù)據(jù)驅(qū)動視圖的,吸收了Angular,Vue,React的各個框架的優(yōu)點,形成了自己的一套規(guī)范。
如果有這方面開發(fā)經(jīng)驗的小伙伴來說,平緩過度到小程序開發(fā)當(dāng)中來,你會發(fā)現(xiàn)總會有驚人的相似,用的語言都是JavaScript,但是與web開發(fā)還是多少有很多差異的,這里就不拓展了。
廢話不多說,直接上代碼 :
小程序前端邏輯代碼:
// 點擊發(fā)送按鈕,對輸入的文本內(nèi)容進(jìn)行校驗
send() {
wx.cloud.callFunction({
name: 'msgSecCheck1', // 云函數(shù)的名稱
data: { // 需要向云函數(shù)傳遞過去的數(shù)據(jù)
content: this.data.textareaVal // 具體要檢測的內(nèi)容
}
}).then(res => { // 成功時,做什么事情
console.log(res);
// 檢測到文本成功時,做一些業(yè)務(wù)
}).catch(err => { // 失敗時,做什么事情
// 失敗時,也就是違規(guī)做一些用戶提示,或者禁止下一步操作等之類的業(yè)務(wù)邏輯操作
console.error(err);
})
}
上面的代碼還可以在優(yōu)化一下,就是將請求云函數(shù)的代碼封裝成一個函數(shù)。
如下所示,不封裝也是沒事的,只是我習(xí)慣性封裝一下,如果其他地方也用到該云函數(shù),那么直接調(diào)用,避免寫重復(fù)的代碼。
下面是將請求云函數(shù)的部分核心代碼:
// 發(fā)布
send() {
// 請求msgSecCheck1云函數(shù),對文本內(nèi)容進(jìn)行校驗
this._requestCloudMsgCheck();
},
_requestCloudMsgCheck() {
let textareaVal = this.data.textareaVal;
wx.cloud.callFunction({
name: 'msgSecCheck1',
data: {
content: textareaVal // 這里可以使用官方文檔測試用例,特3456書yuuo莞6543李zxcz蒜7782法fgnv級
}
}).then(res => {
console.log(res);
// 檢測到文本成功時,做一些業(yè)務(wù)
}).catch(err => {
// 失敗時,也就是違規(guī)做一些用戶提示,或者禁止下一步操作等之類的業(yè)務(wù)邏輯操作
console.error(err);
})
}
至于是在失去焦點事件時發(fā)送請求還是在點擊發(fā)送按鈕時發(fā)送請求,兩種方式都可以。
您也可以自定義文本校驗,而我個人覺得在小程序端,失去焦點時,可以自定義做一些常規(guī)敏感詞的弱校驗,而在點擊發(fā)送按鈕時,做強(qiáng)校驗 。
如果是放在失去焦點時就立馬請求,這樣請求次數(shù)會增多,而放在點擊發(fā)送按鈕時進(jìn)行校驗,一定程度上可以減少小程序端頻繁請求。
接下來就是處理云函數(shù)端,使用request-promise請求請求微信內(nèi)容安全接口的示例代碼。
/*
* Description: 利用第三方庫request-promise請求微信內(nèi)容安全接口
*
* 相關(guān)文檔鏈接:
* 微信文本內(nèi)容安全接口文檔https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
* access_token獲取調(diào)用憑證文檔
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html
*
* request-promise使用文檔: https://github.com/request/request-promise
*
*/
const APPID = "wx21baa58c6180c2eb"; // 注意是你自己小程序的appid
const APPSECRET = ""; // 你自己小程序的appsecret
// 安全校驗接口
const msgCheckURL = `https://api.weixin.qq.com/wxa/msg_sec_check?access_token=`;
// 向下面的這個地止發(fā)送請求,攜帶appid和appsecret參數(shù),獲取token認(rèn)證
const tokenURL = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`
// 云函數(shù)入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 引入request-promise
const rp = require('request-promise');
// 云函數(shù)入口函數(shù)
exports.main = async(event, context) => {
try {
let tokenResponse = await rp(tokenURL);
// 獲取token值,因為返回的結(jié)果是字符串,需要用JSON.parse轉(zhuǎn)化為json對象
let getAccessToken = JSON.parse(tokenResponse).access_token;
// 請求微信內(nèi)容安全接口,post請求,返回最終的校驗結(jié)果
let checkResponse = await rp({
method: 'POST',
url: `${msgCheckURL}${getAccessToken}`,
body: {
content: event.content // 這里的event.content是小程序端傳過來的值,content是要向內(nèi)容接口校驗的內(nèi)容
},
json: true
})
return checkResponse;
} catch (err) {
console.error(err);
}
}
當(dāng)你在小程序端輸入文本,發(fā)送請求時,查看控制臺下的結(jié)果時,功能是沒有問題的。
特3456書yuuo莞6543李zxcz蒜7782法fgnv級 完2347全dfji試3726測asad感3847知qwez到
您可以根據(jù)官方文檔中提供的測試用例,進(jìn)行測試,看具體的返回結(jié)果的。
(控制臺錯誤碼)
(合規(guī)內(nèi)容)
云函數(shù)請求成功,看看錯誤信息的反饋,對于熟悉該錯誤碼的人清楚該文本違規(guī)了,但是反饋不是很明顯,即使當(dāng)下自己很清楚,然而,在過幾個月在回來看代碼,你或許都不知道是啥意思。
對于處理錯誤碼,返回具體的合適信息,對于調(diào)試代碼,排查問題,也是非常重要 。
這些錯誤碼具體的含義,在官方文檔里都有對應(yīng)的解釋,不用去記,去查文檔就行。
在面試中,有很多面試官喜歡問http相關(guān)狀態(tài)碼的問題,狀態(tài)碼有很多,也真的記不住,但是常見的錯誤http狀態(tài)碼還是要知道的,我覺得,具體知道怎么處理,怎么查文檔就可以了。
真正考驗背后目的是,對于根據(jù)后端返回的狀態(tài)碼,判斷接口哪里出了問題,定位是前端問題還是后端問題,這是一個非常常見的問題。
如果你說你不知道,沒有處理過,對于候選人,那肯定是沒有信服力的,無論是成功狀態(tài)還是失敗狀態(tài),都是應(yīng)該有對應(yīng)的用戶提示。
/*
*
* 相關(guān)文檔鏈接:
* 微信文本內(nèi)容安全接口文檔https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
* access_token獲取調(diào)用憑證文檔
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html
*
* request-promise使用文檔: https://github.com/request/request-promise
*
*/
const APPID = "wx21baa58c6180c2eb";
const APPSECRET = "";
const msgCheckURL = `https://api.weixin.qq.com/wxa/msg_sec_check?access_token=`;
// 向下面的這個地止發(fā)送請求,攜帶appid和appsecret參數(shù),獲取token認(rèn)證
const tokenURL = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`
// 云函數(shù)入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 引入request-promise
const rp = require('request-promise');
// 云函數(shù)入口函數(shù)
exports.main = async(event, context) => {
try {
let tokenResponse = await rp(tokenURL);
// 獲取token值,因為返回的結(jié)果是字符串,需要用JSON.parse轉(zhuǎn)化為json對象
let getAccessToken = JSON.parse(tokenResponse).access_token;
// 請求微信內(nèi)容安全接口,post請求,返回最終的校驗結(jié)果
let checkResponse = await rp({
method: 'POST',
url: `${msgCheckURL}${getAccessToken}`,
body: {
content: event.content // 這里的event.content是小程序端傳過來的值,content是要向內(nèi)容接口校驗的內(nèi)容
},
json: true
})
// 有必要根據(jù)錯誤碼,確定內(nèi)容是否違規(guī)
if (checkResponse.errcode == 87014) {
return {
code: 500,
msg: "內(nèi)容含有違法違規(guī)內(nèi)容",
data: checkResponse
}
} else {
return {
code: 200,
msg: "內(nèi)容OK",
data: checkResponse
}
}
} catch (err) {
if (err.errcode == 87014) {
return {
code: 500,
msg: '內(nèi)容含有違法違規(guī)內(nèi)容',
data: err
}
} else {
return {
code: 502,
msg: '調(diào)用msgCheckURL接口異常',
data: err
}
}
}
}
在云函數(shù)端,經(jīng)過添加錯誤碼的判斷之后,在來看看小程序端發(fā)送的請求,返回的結(jié)果。
(這與沒有添加錯誤碼判斷,是不一樣的,有具體的錯誤信息內(nèi)容)
至此,我們在小程序端可以根據(jù)這個返回的錯誤碼或成功碼,進(jìn)行一些業(yè)務(wù)邏輯處理的,比如給一些用戶提示,在數(shù)據(jù)插入數(shù)據(jù)庫之前就做一些判斷操作,只有內(nèi)容合規(guī)時,才插入數(shù)據(jù)庫,進(jìn)入下一步的業(yè)務(wù)邏輯處理。
_requestCloudMsgCheck() {
let textareaVal = this.data.textareaVal;
wx.cloud.callFunction({
name: 'msgSecCheck1',
data: {
content: textareaVal
}
}).then(res => {
console.log(res);
const errcode = res.result.data.errcode;
// 檢測到文本錯誤時,做一些業(yè)務(wù)
if (87014 === errcode) {
wx.showToast({ // 當(dāng)內(nèi)容違規(guī)時,做一些用戶提示
title: '您輸入的文本內(nèi)容含有敏感內(nèi)容,請重新輸入',
})
}else {
// 成功時做其他業(yè)務(wù)操作
}
}).catch(err => {
// 失敗時,也就是違規(guī)做一些用戶提示,或者禁止下一步操作等之類的業(yè)務(wù)邏輯操作
console.error(err);
})
}
(當(dāng)輸入的內(nèi)容有違規(guī)時,給一些用戶提示或者阻止下一步操作等的)
注意在云函數(shù)(后)端處理錯誤碼與小程序端都是要進(jìn)行處理的,兩者不要混淆了的,小程序端最終的一些業(yè)務(wù)邏輯判斷,是根據(jù)后端接口返回的狀態(tài),最終決定要做什么操作的。
至此,通過request-promise庫就完成了文本內(nèi)容校驗的問題。
這個request,request-promise庫非常實用,功能也非常強(qiáng)大,類似這種庫,常見什么got,axios等之類的,都是支持promise風(fēng)格的 處理方式大同小異,大家可以去npm或github上閱讀相關(guān)使用文檔的。
在小程序中有多種解決方案,推薦使用小程序端請求云開發(fā)云函數(shù)的方式,無論是不使用云函數(shù)方式,自己有后端服務(wù),獲取access_token都應(yīng)該是從后端返回給前端的。
而小程序的秘鑰 AppSecret是不應(yīng)該放在小程序端的,那樣不安全的,無論是服務(wù)器開發(fā)模式還是小程序·云開發(fā)模式,都繞不過后臺請求微信提供的內(nèi)容安全接口,然后在返回給小程序端 。
其實在小程序·云開發(fā)中,還提供了一種更簡便的方法,那就是云調(diào)用,它是小程序·云開發(fā)提供的在云函數(shù)中調(diào)用微信開放接口的能力,只需簡單的進(jìn)行配置一下就可以了。
限于篇幅所致,放在下一節(jié)介紹。
reference:方案1參考鏈接:
微信內(nèi)容安全:
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
云調(diào)用
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/capabilities.html#%E4%BA%91%E5%87%BD%E6%95%B0
百度文本審核
https://ai.baidu.com/tech/textcensoring
網(wǎng)易云盾
https://dun.163.com/product/text-detection
公眾號:騰訊云云開發(fā)
騰訊云云開發(fā): https://cloudbase.net
云開發(fā)控制臺: https://console.cloud.tencent.com/tcb?from=12304