配置:
- 前端: ng11 + ng-zorro + material + ionic - 后端: JAVA + py 先说下背景: 目前的活体检测可以大致分为三个类型: - 静默活体 ?前端传一张或多张照片给后端,后端通过算法模型进行比对,计算出是否是活体,这种活体认证风险较大,易被以假乱真。 - 动作活体 ? ? ?- 前端动作活体: ? ? ? ? ?- 由前端基于webRtc拿到视频流后,利用js算法模型,对视频流中的人脸进行识别、验证,最终检测出是否为活体。(目前我们采用的库是[(human)](https://github.com/vladmandic/human),是一个国外大神基于tensorflow开源的算法模型进行封装、改进开发的,有问题可以随时提issue,大神欢迎大家提issue,并尽可能立刻解答。 ? ? ?- 后端动作活体: ? ? ? ? ?- 前端通过网络将资源传输到后端,后端统一处理需要检测的图像或视频流,对后端的架构有一定的挑战,同时网络的延时往往不能给用户带来实时的交互效果。 - 视频活体 ? ? - 有两种方案: ? ? ? ? 1. 前端通过实时发送照片,后端实时进行活体判断,返回检测结果。这种比较耗带宽和后端资源,并且直接发人脸照片数据给后端,容易被劫持,有一定的安全性问题。 ? ? ? ? 2. 前端拍摄一段含有人脸的视频(1~3s),后端拿到之后直接通过算法引擎进行解析,返回是否为活体的结果,这部分是有坑需要去填的, ? ? ? ? ? ? 1. 因为要保证视频在不同平台都能播放,一般要为mp4格式,而通过RecordRTC(webRtc提供的录像接口),是无法直接录制mp4格式的视频的,这就要转格式,后端转格式的话很简单,用ffmpeg这个库就能解决了,而如果要前端来转格式的话,就有些坑了,[目前我找到了某佬写的算法](https://github.com/OllieJones/webm2mp4-js),转化之后用pc可以正常播放,但是ios只能播放第一秒,目前还没有解,待后端解了之后会更新解法。 ? ? ? ? ? ? 2. 首先webRtc有兼容性问题、其次RecordRtc也有兼容性问题,具体可以查下mdn. 目前,我已经做了基于webRtc的流进行静默活体和动作活体检测(包括摇头、点头、张嘴、眨眼),stream(视频流)在webRtc中是个关键点,如果拿不到stream,所有功能都不可用,因此有些浏览器是用不了我们的活体验证的,于是乎,产品就急了,因为我们项目里刷脸功能大多数是to C的场景,所以,要保证大部分人可以使用刷脸功能。
过程是这样的: - 产品要把我们原先刷脸登录的H5嵌入到微信公众号里,并能够有效保证,用户的照片是通过现场拍摄上传的,而不是从相册里选择上传。 好了,废话(铺垫)讲得有点多,下面进入正题,调用微信JS-SDJ进行刷脸到底有什么坑? - ?首先的大坑在于wx.config在ios中的坑。 ? ? - 明明配置相同,android是好的,iOS真机一直报config:invalid signature? ? ? 去微信开放社区搜一下就会发现,有很多类似的问题,微信官方也给了解法: ? ??
但是、这种解法根本不奏效,最后一条只说了部分真相,就是不说ios和android在微信里路由渲染的差异。 ? - 首先要知道wx.config是有限制的,请求签名的页面要和wx-config的页面一模一样,除了hash值,其他的参数都要带上,配置之后其他页面就可以用js-sdk中的方法了,安卓的微信每次跳转路由后,真实页面都会根据路由来刷新。 ? - 而ios的则不然,当你通过一个页面(index.html)进入微信之后,页面就会被微信打上一个标签,路由再去跳转到其他页面,实际上路由是没有变的,所以这个时候如果再去进行wx.config就会报config:invalid signature,而angular的每一个app,实际上都会被打包成index.html和其他资源文件,微信会基于这个index.html进行打标签,在ios里,每一个app对于wx来说就是一个页面,里面的路由再跳转都是不会刷新的了,**所以在angular里需要wx.config的aoo对应的app.compoennt.ts里,需要获取一下当前地址,然后在调微信配置的时候把这个url传过去,再把拿到的配置给wx.config就ok了,里面的module里就都能用了.** ??
我这里目前是写了一个全局service里的变量.
说完ios的坑,下面是andriod的坑. 微信js-sdk拍照提供了一个chooseImage方法,这里可以指定只能用手机摄像头(虽然有兼容性问题),拍完照之后可以拿照片的base64.坑的地方就在这了,ios可以直接通过getLocalImgData方法的返回值,拿localData,就是当前图片的base64,而android是拿不到的,需要先拿到localId创建一个img标签,然后再用canvas把img里的照片转成base64。
``` export async function imageCutBySrc(image: string, width?: number, height?: number, options?: ImageCutOpt) { ? const img = await loadImage(image); ? const imgUrl = await imageCutByHTMLImageElement(img, width, height, options); ? return imgUrl; } ``` ``` /** ?* 加载图片 ?* @param file ?*/ export async function loadImage(img: string) { ? return new Promise<HTMLImageElement>((resolve, reject) => { ? ? const image = new Image(); ? ? image.src = img; ? ? image.onload = () => resolve(image); ? ? image.onerror = function () { ? ? ? reject(); ? ? }; ? }); } ``` 目前用到的就是这两个方法,其他压缩图片的方法我就不发了(因为我们后端的限制,图片要压缩到100k内才能保证认证速度)
其实还有一个坑是 wx.config里的timesteamp是时间戳时间类型,不能是字符串,如果是字符串会报错.
ps: 最近在做微信相关的东西,遇到了这几个坑,并且有些坑微信是一直没有解决了,比如微信js-sdk的chooseImage方法默认配置打开前置摄像头,这个明明小程序都实现的功能了,就不能加到js-sdk里么,如果有相关开发人员看到了,能帮忙填坑那就是再好不过了~ that's all ,over!
|