近期研究很多种登录系统的方式,有邮箱、手机号、QQ、微博、人脸登录等。整合了一下,用SpringBoot写了个简单的小Demo,供大家学习参考。之后在编写项目的时候你就可以选择性整合进去了,可以稍微提升一下项目B格。
这期文章先讲一下我觉得挺好玩的人脸登录,我用的是百度云的人脸识别服务。实现的效果如下:
即然我们用到的是百度云的服务,那么我们首选需要登录百度云的官网
https://console.bce.baidu.com/
注册登录之后好像需要实名认证,认证一下就OK了,很快。
之后我们可以直接在控制台总览搜索【人脸识别】,点击进入
进入之后创建应用,填写应用的信息,应用归属选择个人即可,创建完成之后,我们还需要领取一下免费资源。
然后我们选择管理应用,就可以看到我们所创建应用的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 = 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<String, String> map = (Map<String, String>) 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= '/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
这个示例主要用到了人脸检测、人脸搜索、人脸注册服务,每个服务具体怎么用可以看官网的示例,这里就不做解释了。
大多数服务都需要我们基于人脸的图片去操作和调用,官方给到的图片类型有三种:BASE64字符串、URL字符串、FACE_TOKEN字符串。那么示例中使用的是BASE64字符串进入图片数据的传输。
那么有些人可能不太理解这个Base64是个什么东西,通俗点说就是它把二进制文件转成了可以打印的字符串,这是一种编码方式。
那么后面我们需要做的就是前端调用摄像头,抓取画面内容,将数据内容转为BASE64格式,访问后端接口将数据传递到后端,后端接收到数据后,调用官方的SDK,访问所需要的服务完成调用。
在这些关键步骤的中间会穿插着业务相关的内容,比如没有搜索到人脸后的处理(本示例是自动注册),以及搜索都结果后调用数据库,查询用户的详细信息、以及前端如何调用摄像头,如何连续像后端发送人脸登录请求等。
需要注意的细节还是不少的,但是核心的思路就是上面这些。
那么这个就是所谓的人脸登录了,挺好玩的吧!
获取项目开源地址:微信搜索【薛伟同学】,后台回复【人脸识别】