SpringBoot|简简单单,带你撸个人脸识别登录

近期研究很多种登录系统的方式,有邮箱、手机号、QQ、微博、人脸登录等。整合了一下,用SpringBoot写了个简单的小Demo,供大家学习参考。之后在编写项目的时候你就可以选择性整合进去了,可以稍微提升一下项目B格。
这期文章先讲一下我觉得挺好玩的人脸登录,我用的是百度云的人脸识别服务。实现的效果如下:
SpringBoot|简简单单,带你撸个人脸识别登录
文章图片

SpringBoot|简简单单,带你撸个人脸识别登录
文章图片

登录百度云创建应用 即然我们用到的是百度云的服务,那么我们首选需要登录百度云的官网

https://console.bce.baidu.com/
注册登录之后好像需要实名认证,认证一下就OK了,很快。
之后我们可以直接在控制台总览搜索【人脸识别】,点击进入
SpringBoot|简简单单,带你撸个人脸识别登录
文章图片

进入之后创建应用,填写应用的信息,应用归属选择个人即可,创建完成之后,我们还需要领取一下免费资源。
SpringBoot|简简单单,带你撸个人脸识别登录
文章图片

然后我们选择管理应用,就可以看到我们所创建应用的AppID、API Key和Secret Key了,这三个信息是我们项目调用服务的关键配置。
后端核心逻辑
Lock lock = new ReentrantLock(); /** * 人脸登录注册 */ @PostMapping("/loginByFace") @ResponseBody public ResponseResult loginByFace(String data, HttpSession session) { String base64Prefix = "data:image/png; base64,"; if (StrUtil.isEmpty(data)) { return ResponseResult.failure(ResponseCode.PARAMETER_ERROR); } if (data.startsWith(base64Prefix)) { data = https://www.it610.com/article/data.substring(base64Prefix.length()); } lock.lock(); // 判断是否存在人脸库 ResponseResult searchByBase64 = faceService.searchByBase64(data); if (searchByBase64.getCode() == 0) { // 存在人脸库,登录成功 JSONObject result = (JSONObject) searchByBase64.getData(); Integer id = Integer.valueOf(result.get("user_id") + ""); session.setAttribute("user", userService.get(id)); lock.unlock(); return new ResponseResult(0, "登录成功", null); } // 不存在人脸库,则自动注册 ResponseResult detectByBase64 = faceService.detectByBase64(data, true); if (detectByBase64.getCode() != 0) { lock.unlock(); return detectByBase64; } Map map = (Map) detectByBase64.getData(); String faceToken = map.get("face_token"); // 注册用户 User user = User.builder() .faceId(faceToken) .img("https://moti-cloud-v2.oss-cn-beijing.aliyuncs.com/%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB_o.png") .faceId(faceToken) .name("注册用户" + DateTime.now()) .build(); userService.save(user); session.setAttribute("user", user); faceService.registryByFaceToken(faceToken, user.getId() + ""); lock.unlock(); return ResponseResult.success(); }

前端程序编写 前端我也封装也了一个js文件,把人脸识别需要的方法统一放在此处。
/* 人脸登录相关方法 *///定义变量 let streams; let timers = null; let send; let loginUrl = "loginByFace"; let video = document.getElementById('face-video'); let canvas = document.getElementById('face-canvas'); let context = canvas.getContext('2d'); /** * 发送视频图片 */ function sendImg() { timers = setInterval(function () { if (send) { send = false; context.drawImage(video, 0, 0, 480, 320); let image = canvas.toDataURL('image/png'); $.ajax({ type: "POST", url: loginUrl, data: { data: image, }, dataType: "json", success: function (data) { console.log(data); if (data['code'] === 0) { layer.msg("登录成功"); setTimeout("new function(){window.location.href= 'https://www.it610.com/success'}",1000); } else { layer.msg(data['msg']) send = true } } }); } }, 2000); }/** * 开启摄像头 */ function openCamera() { try { if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) { // 调用用户媒体设备, 访问摄像头 getUserMedia({video: {width: 480, height: 320}}, successCallBack, errorCallBack); } else { alert("启动摄像头失败"); } } catch (err) { alert("受限于浏览器安全策略,无法启动摄像头"); } }/** * 关闭摄像头 */ function closeCamera() { if (streams !== undefined) { streams.stop(); } if (!timers) { clearInterval(timers); } }/** * 访问用户媒体设备的兼容方法 * @param constraints * @param success 成功回调 * @param error 失败回调 */ function getUserMedia(constraints, success, error) { if (navigator.mediaDevices.getUserMedia) { // 最新的标准API navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error); } else if (navigator.webkitGetUserMedia) { // webkit核心浏览器 navigator.webkitGetUserMedia(constraints, success, error) } else if (navigator.mozGetUserMedia) { // firefox浏览器 navigator.mozGetUserMedia(constraints, success, error); } else if (navigator.getUserMedia) { // 旧版API navigator.getUserMedia(constraints, success, error); } }/** * 成功回调 * @param stream */ function successCallBack(stream) { // 兼容webkit核心浏览器 let CompatibleURL = window.URL || window.webkitURL; // 将视频流设置为video元素的源 streams = stream.getTracks()[0]; video.srcObject = stream; video.play(); send = true; sendImg(); }/** * 失败回调 * @param error */ function errorCallBack(error) { alert(`访问媒体设备失败: ${error.message}`); }

之后只需要在前端HTML中加上显示面板即可

实现思路 这个示例中,我们只是作为一个服务的使用者,具体如何使用,那么服务的提供方(百度云),已经提供了非常详细的文件。那么下一步我就就需要找到我们具体所用到的这些接口的文档,详加研究,需要什么参数,我们获取到并且传递给它即可。
更方便的是官方已经帮我们封装好了SDK,相当于提供了工具类,那么我们只需要学习怎么用这个工具类就行了。
https://cloud.baidu.com/doc/FACE/s/8k37c1rqz
SpringBoot|简简单单,带你撸个人脸识别登录
文章图片

这个示例主要用到了人脸检测、人脸搜索、人脸注册服务,每个服务具体怎么用可以看官网的示例,这里就不做解释了。
大多数服务都需要我们基于人脸的图片去操作和调用,官方给到的图片类型有三种:BASE64字符串、URL字符串、FACE_TOKEN字符串。那么示例中使用的是BASE64字符串进入图片数据的传输。
那么有些人可能不太理解这个Base64是个什么东西,通俗点说就是它把二进制文件转成了可以打印的字符串,这是一种编码方式。
那么后面我们需要做的就是前端调用摄像头,抓取画面内容,将数据内容转为BASE64格式,访问后端接口将数据传递到后端,后端接收到数据后,调用官方的SDK,访问所需要的服务完成调用。
SpringBoot|简简单单,带你撸个人脸识别登录
文章图片

在这些关键步骤的中间会穿插着业务相关的内容,比如没有搜索到人脸后的处理(本示例是自动注册),以及搜索都结果后调用数据库,查询用户的详细信息、以及前端如何调用摄像头,如何连续像后端发送人脸登录请求等。
需要注意的细节还是不少的,但是核心的思路就是上面这些。
那么这个就是所谓的人脸登录了,挺好玩的吧!
【SpringBoot|简简单单,带你撸个人脸识别登录】获取项目开源地址:微信搜索【薛伟同学】,后台回复【人脸识别】

    推荐阅读