- 关于接入内容安全API依然被拒解决办法
近期绝大部分小程序收到内容安全能力警告通知如下 [图片] 官方回复一般为: 开发者你好,近期平台收到较多投诉及通报,反馈部分小程序未做好内容审核,存在安全隐患。为完善小程序内容安全生态,近日平台给部分类目陆续下发了相关的隐患提醒,请开发者结合自己实际情况,如未完善内容审核措施的,请尽快完善,可接入平台提供的内容安全接口或其他内容安全能力;如已有相关内容审核措施,请继续加强内容审核力度,做好内容安全掌控。这里并不强制必须要接入微信官方提供的安全接口。 不少开发者认为仅仅接入内容安全API就足够了吗? 其实微信官方提供的内容安全接口并不是万能的,也可能存在错报或不能正确识别的情况,特别是图片安全接口,违法违规信息可以任意展示,同时微信官方也没有强制必须要求接入微信官方提供的安全接口, > 官方内容传播控制策略建议(摘自:珊瑚内容安全用手[小程序]) 1、用户发布内容在未经审核前,建议限制内容传播范围,包括限制转发、访问,或不得在搜索结果中曝光。 2、运营者可根据文字、图片等鉴别能力的检测返回结果,自行对存在风险的内容及时删除、拦截处理。 3、对达到一定访问量或短时间转发次数异常的内容,建议运营者安排人工进行二次审核,及时发现有害内容。 4、对于恶意发布有害内容的用户账号,运营者可作限制使用、封停等处置,从账号维度强化内容管理。 5、对于封停账号,运营者可采取策略限制恶意用户再次使用产品。 所以仅仅接入内容安全API仍然是有相当一部分小程序被下架,但又不知道如何整改 根据我们自己的审核经验,总结了如下解决方法, 接入内容安全API 用户自行发布内容,需先经过内容安全API检测,此时无论通过与否,均不可展示给发布内容的用户及其他用户 再次进行人工审核 通过内容安全API检测后,因为内容安全API并不是能过滤所有有害信息,所以需要再次进行人工审核,审核无误后进行信息展示 说起来很简单,就是加上人工审核这一个环节,并在小程序代码上传时的项目备注里加上:已接入内容安全API,并有人工审核机制 有人可能会说人工审核这样的话效率不是大打折扣了吗?但我认为在大环境下这种牺牲是值得的,希望能帮助到大家
2020-05-07 - 云服务器调用security.imgSecCheck完成代码分享
云服务器代码: // 云函数入口文件 const cloud = require(‘wx-server-sdk’) cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const {value} = event; try { const res = await cloud.openapi.security.imgSecCheck({ media: { header: {‘Content-Type’: ‘application/octet-stream’}, contentType: ‘image/png’, value:Buffer.from(value) } }) return res; } catch (err) { return err; } } 本地函数: wx.chooseImage({count: 1}).then((res) => { if(!res.tempFilePaths[0]){ return; } console.log(JSON.stringify(res)) if (res.tempFiles[0] && res.tempFiles[0].size > 1024 * 1024) { wx.showToast({ title: ‘图片不能大于1M’, icon: ‘none’ }) return; } wx.getFileSystemManager().readFile({ filePath: res.tempFilePaths[0], success: buffer => { console.log(buffer.data) wx.cloud.callFunction({ name: ‘checkImg’, data: { value: buffer.data } }).then( imgRes => { console.log(JSON.stringify(imgRes)) if(imgRes.result.errorCode == ‘87014’){ wx.showToast({ title:‘图片含有违法违规内容’, icon:‘none’ }) return }else{ //图片正常 } [代码] } ) }, fail: err => { console.log(err) } } ) 我相信做出来的人很多,但是没有分享出来,我今天分享出来就是为了避免更多程序员不要在这种简单的问题上,浪费太多的时间,我就浪费了很多时间,兼职太坑爹了[代码]
2019-07-26 - 内容安全检测图片API:openapi.security.imgSecCheck完美解决方案。
背景需求: 我个人做了一款小程序的小游戏,本质是小程序。里面有个自定义图片的功能。用户从本地相册选一张图片进行裁剪,之后保存到缓存中或者上传到服务器。然后用户再用这张图片作为素材进行其它操作。这里就涉及到内容安全了,提交审核没有通过也是因为这个没有做内容安全。防止一些色情低俗的事情发生。 正文: 思路:相册选图片 --> 裁剪小的图片 --> 内容安全检测 --> 通过 --> 裁剪大的图片 --> 保存。 失败的原因:绝大多数是因为检测图片不能大于1M,而导致超时,或者是errCode:-1,又或者是其它问题。 [图片] [图片] 核心代码图片: [代码]默认裁剪小尺寸图片 (我的业务需求是正方形图片,也可动态计算宽高比例) [代码] [图片] 检测图片 部分iOS不兼容encoding: ‘ucs2’。注释掉就好了 [图片] [图片] 云函数 [图片] 测试情况: 正常图片不含违法违规,测试20次,全部通过。小程序上线后暂无发现检测失败情况。百度搜索的“人体油画”等等均可通过。 PS:第一次写经验分享哈,看不懂可以问我。体验一下我的小程序想问我这个小程序其它的功能点也可以喔! 技术会迭代更新,用到的技术会有时效性,看编辑时间,可能当时的技术现在不适用了
2020-10-22 - 小程序云开发攻略,最棘手的问题
背景 最近小程序非常的火,应公司业务发展要求,开发维护了几款小程序,公司开发的小程序都是由后端提供的接口,开发繁琐而复杂,直到小程序出现了云开发,仔细研读了文档之后,欣喜不已,于是我着手开发了本人的第一款小程序 小程序云开发教程地址 点我查看>> 分析 云开发为开发者提供完整的原生云端支持和微信服务支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代,同时这一能力,同开发者已经使用的云服务相互兼容,并不互斥。 优势 无需自建服务器,数据库,无需自建存储和CDN 数据库模型很简单,就是一个json形式的对象格式 调用服务端云函数自动获取openid,再也没有繁琐的授权登陆流程了,只要进入小程序就是登陆状态,体验真的好 开发迅速,只需要前端就能搞定所有开发工作 需要解决的问题 数据库切换问题 使用过云开发的人都发现云开发切换数据库环境是最头疼的,如果手动去切换容易搞错,不小心在当前环境修改了线上数据库数据 直到官方出了这个函数问题也就迎刃而解 [代码]cloud.updateConfig({ env: ENV === 'local' ? 'dev-aqijb' : ENV }); [代码] 我使用的是服务端云开发功能,为什么要这样判断,因为在开发工具中ENV = ‘local’,所以这么判断一下,保证开发工具中使用的是测试环境数据库 使用taro多端开发框架,借助于webpack,还可以通过process.env.NODE_ENV值区分当前代码开发环境 [代码]await Taro.cloud.init({ env: `${process.env.NODE_ENV === 'development' ? 'dev-aqijb' : 'pro-hljv7'}` /* env: 'pro-hljv7' */ }); [代码] 这样可以保证开发环境和线上环境可以使用对应环境的数据库 数据库字段定义问题 因为JS是弱类型语言,不能像typescript那样静态定义变量类型,这样添加到数据库的字段数量和字段类型都无法控制 我不想用typescript,能不能实现这样的功能呢,可以用superstruct库来实现这个功能 superstruct git地址 点我查看>> 详细使用案例见下方代码 函数文件太多的问题 官方和他人教程的例子都是一个文件对应一个云函数,通过开发体验我发现这样做并不好,当项目有多个表的时候,找个函数文件真的太难了 我们可以将一个表的增删改查函数全部写入一个文件中 教程: 首先每个云函数文件中package.json引入superstruct [代码]{ "dependencies": { "wx-server-sdk": "latest", "superstruct": "latest" } } [代码] 以下代码是一个完整的云函数例子 [代码]const cloud = require('wx-server-sdk'); const { struct, superstruct } = require('superstruct'); cloud.init(); //小区信息 const Model = () => { const db = cloud.database(); const _ = db.command; const collection = db.collection('address'); return { async add(data) { try { data = struct({ name: 'string', //名字 phone: 'string', unit: 'number', //楼单元号 doorNumber: 'string', //门号 communityId: 'string', //小区id _openid: 'string' //用户的id //isDefault: 'boolean' //是否默认地址 })(data); } catch (e) { const { path, value, type } = e; const key = path[0]; if (value === undefined) { const error = new Error(`${key}_required`); error.attribute = key; throw error; } if (type === undefined) { const error = new Error(`attribute_${key}_unknown`); error.attribute = key; throw error; } const error = new Error(`${key}_invalid`); error.attribute = key; error.value = value; throw error; } let res = await this.getList({ _openid: data._openid }); if (res.data.length >= 1) { return { msg: '当前只支持保存一个地址' }; } res = await collection.add({ data, createTime: db.serverDate(), updateTime: db.serverDate() }); return res; }, async getAdressById({ _openid, _id }) { const user = await collection .where({ _openid, _id: _.eq(_id) }) .get(); return user; }, //更新指定的id 先判断手机号修改没,没修改直接就改数据,修改过判断一下库中有没有这条数据 async update(data) { //更新表的操作 }, //删除指定id的shop async remove({ _id, _openid }) { //删除表的操作 }, /** * 获取商列表 * @param {*} option {category 类别, pagenum 页码} */ async getList({ _openid }) { const shopList = await collection .where({ _openid }) .get(); return shopList; } }; }; exports.main = async (event, context) => { const { func, data } = event; const { ENV, OPENID } = cloud.getWXContext(); // 更新默认配置,将默认访问环境设为当前云函数所在环境 console.log('ENV', ENV); cloud.updateConfig({ env: ENV === 'local' ? 'dev-aqijb' : ENV }); let res = await Model()[func]({ ...data, _openid: OPENID }); return { ENV, data: res }; }; [代码] 函数使用方式 [代码]wx.cloud.callFunction({ 'address', //云函数文件名 data: { func: 'add', //云函数中定义的方法 data: {} //需要上传的数据 } }); [代码] 图片 视频等文件 直接打开云开发控制台选择存储直接上传文件,复制url地址就可以放到代码中使用了 扫码体验我的小程序: [图片]
2019-09-29