cocos creator 3.x结合c# .netcore webapi调用微信img_sec_check完成图片内容安全校验

文章讲述了微信小程序在使用图片时需要进行内容检查,以避免敏感信息。开发者分享了如何使用img_sec_check接口进行图片检查,并提供了cocoscreator的代码示例以及后端.netcorewebapi的实现方法,包括图片上传和access_token的处理。同时强调了测试的重要性,确保能识别违规图片。

1.使用场景

微信小程序/小游戏中凡是使用到图片的地方(包含拍摄、本地相册)理论上都需要做图片内容检查,不能出现敏感人物及不良内容。首先代码提交上传的时候审核人员会做检查,如果没接入内容检查是有概率被打回的,有一些能够避开该检查的方法可以在我另一个文章中看到,但这个避开也只是暂时的,仅应付代码提交时的审核人员。最近有几个小游戏被举报下架了,盲猜是官方有类似脚本会周期性检测图片类应用,所以即使过了审核也会在运行期间被查到(虽然站内信显示的是被人举报,但是我有一个app日访问量都是个位数的也被ban了,谁闲着没事去举报一个冷门应用?)。

2.解决方法

没办法了只能老老实实做后端接口去校验了,这里用的是同步方法img_sec_check(参考资料:https://developers.weixin.qq.com/miniprogram/dev/framework/security.imgSecCheck.html),官方是推荐使用异步方法mediaCheckAsync,但由于异步方法对接相对复杂,不是实时获取结果的,使用限制比较大所以放弃。
但img_sec_check也有限制比如图片大小要在1M以内,图片尺寸不能超过750*1334(实际测试下来发现这个尺寸限制貌似没起到作用,只要不是大的离谱都能正常返回结果)。所以主要限制还是在大小上,这个我们可以使用wx.chooseMedia自带的sizeType: [‘compressed’]来压缩图片大小,所以基本不是问题。

img_sec_check最大的麻烦是在文档上,非常简单,简单到连个demo都么有,php和java勉强还能找到,.net就…更别提.netcore了,全网也很少有相关资料于是干脆写了一篇文章方便大家,以后也方便自己。

3.cocos creator代码

onbtnClick() {
    this.lblMessage.node.active = false
    console.log(userInfo.isProduction)
    let _this = this
    wx.chooseMedia({
      count: 1,
      mediaType: ['image'],
      sourceType: ['album', 'camera'],
      maxDuration: 30,
      sizeType: ['compressed'],
      camera: 'back',
      success(res) {
        //成功以后打开
        // 用绝对路径加载设备存储内的资源,比如相册
        const absolutePath = res.tempFiles[0].tempFilePath;
        try {
          //上传图片
          wx.uploadFile({
            url: 'https://localhost:3400/api/ImgCheck/ImageCheck', //仅为示例,非真实的接口地址
            filePath: absolutePath,
            name: 'file',
            formData: {
              'appName': '小程序名字'
            },
            success(res) {
              const checkResult = res.data
              if (checkResult == 'false') {
                //图片校验不合规,显示错误提示
                _this.lblMessage.node.active = true
              }
              else {
                //图片检验通过,做你想做的逻辑吧
                assetManager.loadRemote<ImageAsset>(absolutePath, function (err, imageAsset) {
                  const spriteFrame = new SpriteFrame();
                  const texture = new Texture2D();
                  texture.image = imageAsset;
                  spriteFrame.texture = texture;
                })
              }
            }
          })
        }
        catch (err) {
          console.log(err)
        }
      }
    })
  }

使用了wx.chooseMedia获取图片,然后调用wx.uploadFile上传到服务器,formData用于传递一些自定义字段,比如我的后端服务是支持多个小程序使用的,那就传递当前小程序的名字,后端进行区分。

4.后端.netcore webapi代码

新建netcore webapi应用,首先注入服务

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

在控制器里增加方法

using ImgCheckWebApi.BE;
using ImgCheckWebApi.Common;
using Microsoft.AspNetCore.Mvc;

namespace ImgCheckWebApi.Controllers
{
    [ApiController]
    public class ImgCheckController : ControllerBase
    {
        private IHttpContextAccessor _accessor;
        public ImgCheckController(IHttpContextAccessor accessor)
        {
            _accessor = accessor;
        }

        [HttpPost]
        [Route("api/[controller]/ImageCheck")]
        [DisableRequestSizeLimit]
        public async Task<ActionResult<bool>> ImageCheck()
        {
            try
            {
                //获取图片文件
                var file = HttpContext.Request.Form.Files["file"];
                //获取cocos中自定义字段appName,表示哪个小程序名使用该接口
                var key = HttpContext.Request.Form["appName"][0];
                //EF上下文,用于数据库连接
                imagecheckContext _context = new imagecheckContext();
                //根据app名字获取对应的token,自行实现
                var access_token = _context.SystemConfigInfo.FirstOrDefault(x => x.ConfigName == "access_token" && x.ForUserId == key);
                if (access_token != null && !string.IsNullOrEmpty(access_token.ConfigValue))
                {
                    HttpHelper http = new HttpHelper();
                    WxImageSend send = new WxImageSend();
                    send.access_token = access_token.ConfigValue;
                    send.media = file;
                    var result = await http.ImageSecCheck(send);
                    if (result != null && result.errcode != 0)
                        return false;
                    else
                        return true;
                }
                else
                {
                    //没有注册过的app返回true,已防用户没法用
                    return true;
                }
            }
            catch (Exception ex)
            {
                LogHelper.LogError("ImageCheck异常", ex);
                return true;
            }
        }
    }
}

HttpHelper中的ImageSecCheck方法

public async Task<WxImgSecCheck> ImageSecCheck(WxImageSend send)
        {
            string wxapiImageSecCheckUrl = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + send.access_token;
            string json = String.Empty;
            byte[] bytes = new byte[send.media.Length];
            using (var fileStream = send.media.OpenReadStream())
            {
                fileStream.Read(bytes, 0, (int)send.media.Length);
            }
               
            using (var httpClient = new HttpClient())
            {
                try
                {
                    ByteArrayContent array = new ByteArrayContent(bytes);
                    array.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                    HttpResponseMessage response = await httpClient.PostAsync(wxapiImageSecCheckUrl, array);
                    response.EnsureSuccessStatusCode();
                    string responseBody = await response.Content.ReadAsStringAsync();
                    json = responseBody;
                }
                catch (Exception reqEx)
                {
                    LogHelper.LogError("图片安全校验接口错误", reqEx);
                    return null;
                }
            }
            var obj = DeserializeJsonToObject<WxImgSecCheck>(json);
            return obj;
        }

参数的WxImageSend就是一个实体

 public class WxImageSend
    {
        public string access_token { get; set; }
        public IFormFile media { get; set; }
    }

返回的实体WxImgSecCheck

public class WxImgSecCheck
{
    public int errcode { get; set; }
    public string errmsg { get; set; }
}

如果之前没有使用过access_token,不知道怎么获取的,可以参考官方文档(https://developers.weixin.qq.com/minigame/dev/api-backend/open-api/access-token/auth.getAccessToken.html)如果在.netcore中使用,可以在webapi中使用Quartz定时更新access_token并保存在数据库,上面"//根据app名字获取对应的token,自行实现"的地方就是从数据库拿取这个access_token的。
Quartz如果有需求的话以后再写个文章介绍吧,功能非常强大可以维护access_token,也可以拿来定时刷新游戏排行榜等等。

搭完这个后端就完成图片内容校验了,妈妈再也不用担心我的小游戏被ban了。另外提醒一点,如果数据格式不对调用了img_sec_check,接口也会返回ok,不能看到ok就认为搞定了,要拿违规的图去做测试,得到高风险结果了才能认为是真的ok了,哪些是违规图,可以百度一些高官的图片,拿这图片去做测试。

以上,有疑问可以留言~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰机大大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值