活体检测代码提交

This commit is contained in:
袁帅
2022-10-24 17:06:53 +08:00
parent 4965600636
commit 38fd61e948
8 changed files with 753 additions and 25 deletions

View File

@ -1,15 +1,17 @@
import React, { useEffect, useState, useRef } from 'react';
import { Form, Button, Input, Row, Col, Modal, Spin, message, Tabs } from 'antd';
import { UserOutlined, LockOutlined, SafetyCertificateOutlined, VideoCameraOutlined } from '@ant-design/icons';
import { UserOutlined, LockOutlined, SafetyCertificateOutlined } from '@ant-design/icons';
import './style.less';
import { changePass, rgbToBase64 } from './service';
import { changePass } from './service';
import logo from '@/images/login/logoPic.png';
import { refreshTokenApi, ZjfakeAccountLogin, ZjfakeFaceLogin } from '@/services/login';
import { history } from 'umi';
import cookie from 'react-cookies';
import moment from 'moment';
import FrameFaceLogin from '../faceLogin/FrameFaceLogin';
import { fromPairs } from 'lodash';
import Living from './living.min.js';
import { _KJUR } from './jsrsasign-latest-all-min';
import { time } from 'echarts';
const layout = {
labelCol: { span: 7 },
@ -35,7 +37,147 @@ const Index: React.FC<{}> = () => {
const mediaStreamTrack = useRef<any>();
const { TabPane } = Tabs;
const [submitLoading, setSubmitLoading] = useState<boolean>(false);
const [faceLoginDisable, setFaceLoginDisable] = useState<boolean>(false);
const [faceLoginDisable, setFaceLoginDisable] = useState<boolean>(false);
const lv = useRef<Living>();
const [timerShow, setTimeShow] = useState<boolean>(false);
const [itemShow, setItemShow] = useState<boolean>(false);
const [action, setAction] = useState<number>(1);
const [timer, setTimer] = useState<number>(10000);
/**
* 设置活体检测token
*/
const setLiveDetectToken = () =>{
let appKey= 'nkYy3g1yT0alE8pF6a1UTC4I'
let appSecrect = 'L30zHpTyAtTlY7tTCpbzdxxKCQgwWIQL'
// Header
var header = {
typ: "JWT", // 声明类型
alg: "HS256" // 声明加密的算法 通常直接使用 HMAC SHA256
};
var payload = {
iss: appKey,
iat: moment().unix(),
exp: moment()
.add(29, "minutes")
.unix()
};
var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(payload);
var sJWT = _KJUR.jws.JWS.sign("HS256", sHeader, sPayload, {
utf8: appSecrect,
});
console.log(sJWT);
return sJWT;
};
/**
* 开始人脸识别(活体和比对)
*/
const liveDetectStart = () => {
liveDetectStop();
let _lv = new Living(null, {
timer: 10000,
action : [1,3,2],
token: setLiveDetectToken(),
proxy:'/living/api',
getFacePicture:()=>{
return getLiveDetectFile()
},
//开始活体检测此时token已鉴权成功
onDetectStart:()=>{
setSubmitLoading(true);
},
//每轮检测开始
onDetectActionStart:(action:number)=>{
setAction(action);
// this.drawCanvas()
},
//每轮检测计时
onDetectActionProgress:(action:number,timer:number)=>{
setTimer(timer);
},
//每轮检测结束
onDetectActionFinish:(action:number,data:any)=>{
// this.clearCanvas()
setTimer(10000);
console.log(data)
},
//活体检测完成
onDetectFinish:(data:any)=>{
if(data.code == 1){
setAction(4);
setTimeShow(false);
//人脸比对
hanleFaceSubmit(data.file.file, null);
}else{
message.error('活体检测失败');
setSubmitLoading(false);
}
// data.code === 1? message.success('活体检测通过'):message.error('活体检测失败')
}
});
//开始检测
_lv.start();
lv.current = _lv;
}
/**
* 停止活体检测
*/
const liveDetectStop = () => {
lv.current && lv.current.stop();
}
/**
* 给活体检测提供照片
* @returns 活体照片
*/
const getLiveDetectFile = () => {
const canvas = document.createElement('canvas');
canvas.setAttribute('width', '300');
canvas.setAttribute('height', '200');
const context = canvas.getContext('2d');
context.drawImage(video.current, 0, 0, 300, 200);
let _imgURI = canvas.toDataURL("image/jpeg",);
console.log(_imgURI);
let _file = base64ToBlob(_imgURI);
return {
file:_file//传给活体检测服务的文件
}
}
const classColor = (action:any) => {
let color = '';
switch(action){
case 1:
color = '#409eff';
break;
case 2:
color = '#5daf34';
break;
case 3:
color = 'gold';
break;
case 4:
color = 'grey';
break;
}
return color;
}
const actionText = (action:number, timer:number) => {
let text = '';
switch(action){
case 1:
text = '对准摄像头眨眨眼('+ timer + 's';
break;
case 2:
text = '对准摄像头张张嘴('+ timer + 's';
break;
case 3:
text = '对准摄像头摇摇头('+ timer + 's';
break;
case 4:
text = '请稍候,正在验证中...';
}
return text;
}
const genRandomString = (len: number) => {
const text = 'abcdefghijklmnopqrstuvwxyz0123456789';
@ -138,6 +280,7 @@ const Index: React.FC<{}> = () => {
const canvas = document.createElement('canvas');
canvas.setAttribute('width', '300');
canvas.setAttribute('height', '200');
document.body.appendChild(canvas);
const context = canvas.getContext('2d');
context.drawImage(video.current, 0, 0, 300, 200);
canvas.toBlob(function (result: any) {
@ -236,9 +379,9 @@ const Index: React.FC<{}> = () => {
};
//访问用户媒体设备的兼容方法
const InitUserMedia = (constraints: any, success: any, error: any) => {
if (navigator.mediaDevices.getUserMedia) {
if (navigator.mediaDevices?.getUserMedia) {
//最新的标准API
navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
navigator.mediaDevices?.getUserMedia(constraints).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
navigator.webkitGetUserMedia(constraints, success, error);
@ -285,17 +428,16 @@ const Index: React.FC<{}> = () => {
return new Blob([uInt8Array], { type: contentType });
};
//RgbToBase64
const RgbToBase64 = async (image: any) => {
//IELiveDetectFinish
const IELiveDetectFinish = async (data: any) => {
setSubmitLoading(true);
// await rgbToBase64({ image }).then(res => {
// const _blob = base64ToBlob('data:image/jpg;base64,' + res.data);
// hanleFaceSubmit(_blob, null);
// }).catch(e => {
// setSubmitLoading(false);
// });
console.log(1, image);
hanleFaceSubmit(base64ToBlob(image), null);
setAction(4);
hanleFaceSubmit(base64ToBlob(data.file.file), null);
}
const UpdateDetectStatus = async(action:number, timer:number)=>{
setAction(action);
setTimer(timer);
}
//是https或者是本地
@ -415,7 +557,8 @@ const Index: React.FC<{}> = () => {
className="form-box"
initialValues={{ remember: true }}
form={form2}
onFinish={hanleFaceSubmit.bind(this, null)}
// onFinish={hanleFaceSubmit.bind(this, null)}
onFinish={!whetherIE.current?liveDetectStart:hanleFaceSubmit.bind(this, null)}
// onFinishFailed={onFinishFailed}
>
<Form.Item
@ -431,13 +574,20 @@ const Index: React.FC<{}> = () => {
/>
</Form.Item>
{/* 加载摄像头 */}
{/* <Form.Item hidden={!itemShow}>
<div>
<span style={{color:classColor(action)}}>{actionText(action)}</span>
<span hidden={!timerShow}>{Math.round(timer/1000)}</span>
</div>
</Form.Item> */}
<Form.Item>
{!whetherIE.current ? (<video ref={video} width="382" height="200"></video>) : (<FrameFaceLogin faceCompareEvent={RgbToBase64} />)}
{!whetherIE.current ? (<video ref={video} width="382" height="200"></video>) : (<FrameFaceLogin faceCompareEvent={IELiveDetectFinish} faceDetectStatusEvent = {UpdateDetectStatus}/>)}
{/* <video ref={video} width="382" height="200"></video> */}
</Form.Item>
<Form.Item>
{/* onClick={() => {hanleFaceSubmit(null, null);}} */}
<Button type="primary" className="w100" loading={submitLoading} htmlType="submit">
{submitLoading ? '请稍候,正在验证中...' : '登 录'}
{submitLoading ? actionText(action, Math.round(timer/1000)) : '登 录'}
</Button>
</Form.Item>
</Form>