本站首页 返回顶部 关于博主

为小程序的图片增加安全内容检查

PDF版

9月30日晚上,突然收到一条微信,提示 图片水印工具 因涉嫌违规,封禁“被搜索”能力,如下图所示。

第一反应这是个误会。图片水印工具是一个本地小程序,仅在用户的手机本地对图片进行处理。不涉及任何网络传输,没有服务端,用户也不无法把自己的图片分享给他人,不可能存在“内容安全”相关的问题。小程序上线一年半,没有扩展新的功能,最近一次更新是一年前修复一个小 bug。

10月1日,我发起了申诉,在申诉中说明了小程序的功能和相关证据。很意外,10月10日收到回复,申诉失败。结果中提示“该小程序中涉嫌存在政治敏感信息等内容安全问题,未接入内容安全接口相关能力及建立审核巡查机制。”

我郁闷了,看来这次禁封不是误会。

怎么解决呢?在Google的帮助下,知道了真相,原来9月底大量图片处理相关的小程序在毫无征兆的情况下被封禁,看来图片水印工具被封禁不是个例啊。很多网友给出了解决方案:对于图片处理的小程序,都应该接入微信的安全检查 API:imgSecCheck,即所有的图片在处理之前,都应该使用 imgSecCheck 进行检查,连本地运行的小程序也不例外。

改吧,人在屋檐下,不得不低头。

思路

在小程序的内容安全中找到 security.imgSecCheck 函数的说明,这个函数必须在服务端调用,需要给它传 2 个参数,1个是 accessToken,一个是图片的内容。

图片水印工具是一个纯客户端的应用,没有服务端。如果要调用 imgSecCheck,那必须增加一台服务器,做 2 件事情:1. 在服务器端维护好 accessToken,保证每2小时更新一次;2.增加一个 API 供小程序端调用,当小程序调用这个API时,服务端调用 imgSecCheck,并把返回值返回给小程序。

为了增加一个内容安全检查的功能,增加一台服务器,成本有点高。有没有其他的方案呢?

庆幸的是,微信最近引入了云开发的功能。采用云开发作为服务端,应该可以节省不少成本。

实现

那就决定采用云开发。

先在本机搭建云开发环境,云开发的服务端是 nodejs。详细步骤可参见:小程序云开发全套实战教程,本文不再赘述。

接下来,创建云开发(服务端)的API,命名为 imgSecCheck,在index.js文件中加入安全内容检查的代码,代码如下:

// 云函数入口文件
const cloud = require('wx-server-sdk')

// 初始化云开发
cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  var imgType = event.contentType;
  var imgContent = event.value;
  var buffer = Buffer.from(imgContent);

  try {
    var result = await cloud.openapi.security.imgSecCheck({
      media: {
        contentType: imgType,
        value: buffer
      }
    })
    return result
  } catch (err) {
    return err
  }
}

我们来读一下这段代码。第 10 行、11行先读取两个参数 contentType、value,其中 contentType 是图片类型,可能值是“image/png”、“image/jpg”等常见的图片类型,第二个值是图片数据,类型为 ArrayBuffer。

由于 腾讯的图片内容检查函数可接受的图片数据为 Buffer,所以需要使用 Buffer.from() 转换成 Buffer。第15行 ~ 第20行是调用腾讯的内容检查函数security.imgSecCheck,获取结果之后再返回给小程序端。

本来在调用 security.imgSecCheck 函数时,需要传入参数 access_token,以确保调用方的可信度。在腾讯看来,云开发环境是天然的可信方,所以云开发在调用时无需 access_token。

以上是服务端的实现,现在我们开发小程序端。

首先,通过 wx.getImageInfo() 获取图片的类型,然后使用  wx.getFileSystemManager().readFile() 读取文件,获取的数据 res.data 即是文件 Buffer,最后调用刚才开发的云函数既可以了。详细代码如下:

var imgType = res.Type;

wx.getFileSystemManager().readFile({
    filePath: fileTypeValue,
    success: function (res) {

	wx.cloud.callFunction({
   	// 云函数名称
   	name: 'imgSecCheck',

  	 // 传给云函数的参数
 	  data: {
   	    contentType: 'image/' + imgType,
   	    value: res.data,
 	  },
 	  success: function (res) {
 	      if( res.result && res.result.errCode == 0 )
 	      {
 	        ...
 	       }else
 	       {
   	         wx.showToast({
    	            title: '根据腾讯规定,此图片不符合安全规范,不予显示。',
                    icon: 'none',
                    duration: 3000
 	         });
 	       }
 	  },
 	  fail: function( res )
 	  {
           ...
 	  }
    });
});

最后,把服务端代码上传到云开发环境,就可以运行了。

总结

使用云开发环境,免去了 access_token 的维护工作,一定程度上也简化了开发,挺好的。

在重新提交代码之后,很快就审批了,我也把它提交上线了。

只是,我心里仍旧有很深的疑虑:一个在用户本地处理图片的小程序,无需上传图片,也没有分享功能,怎么可能存在内容不安全因素呢?加上内容安全检查功能,一方面增加开发者的工作量;另一方面,在浪费用户流量的同时,也影响了小程序的性能;另外,腾讯公司不得不耗费大量的人力物力进行审核工作,对任何一方而言,没有人受益。我不禁要问:这个内容安全检查功能真的这么重要吗?

除了刚才提到的成本损失外,在毫无征兆的情况下,大面积封禁小程序,已有的开发者对小程序的信心恐怕会大打折扣,而正在犹豫是否要开发的小程序的开发者,很有可能会打退堂鼓。

后续

增加“安全内容检查”之后,重新提交上线了。可是“被搜索”功能仍旧被限制。我也找不到任何申诉渠道。也就是说,从今以后,用户无论如何都搜索不到 图片水印工具 这个小程序了。向小程序的客服反馈,也没有回音。

国庆之后的10天,每天的新增用户只有以前的10%。看着断崖式下跌的新增用户数,心里在滴血。

当然,我是幸运的。在尝试各种渠道之后,今天早上恢复了“被搜索”功能。但我心里的石头仍旧悬着,下一次毫无征兆地封禁什么时候到来呢?




请你留言