import React, { useEffect, useState, useRef } from 'react'; import { Form, Button, Input, Row, Col, Modal, Spin, message, Tabs } from 'antd'; import { UserOutlined, LockOutlined, SafetyCertificateOutlined } from '@ant-design/icons'; import './style.less'; 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 LivingNotIE from './living.min.js'; import { _KJUR } from './jsrsasign-latest-all-min'; import { time } from 'echarts'; const layout = { labelCol: { span: 7 }, wrapperCol: { span: 13 }, }; export interface RgbParams { type: string; image: string; } const Index: React.FC<{}> = () => { const [form] = Form.useForm(); const [form2] = Form.useForm(); const [imgUrl, setImgUrl] = useState(''); const [tmpToken, setTmpToken] = useState(''); const remainingTime = 3 //刷新token的剩余时间,单位小时 const [changeForm] = Form.useForm(); const [isModalVisible, setIsModalVisible] = useState(false) const [spinning, setSping] = useState(false);//加载遮罩 const video = useRef(); const whetherIE = useRef(false); const mediaStreamTrack = useRef(); const { TabPane } = Tabs; const [submitLoading, setSubmitLoading] = useState(false); const [faceLoginDisable, setFaceLoginDisable] = useState(false); const lv = useRef(); const [timerShow, setTimeShow] = useState(false); const [itemShow, setItemShow] = useState(false); const [action, setAction] = useState(1); const [timer, setTimer] = useState(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 LivingNotIE(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'; const rdmIndex = (text: string | any[]) => (Math.random() * text.length) | 0; let rdmString = ''; for (; rdmString.length < len; rdmString += text.charAt(rdmIndex(text))); return rdmString; }; const changeCaptcha = () => { let tmpToken = genRandomString(16); let url = '/api/auth/captcha?token=' + tmpToken; setTmpToken(tmpToken); setImgUrl(url); }; //登录刷新Token方法 const refreshToken = async (data: any) => { const params = { grant_type: "refresh_token", refresh_token: data?.refreshToken?.value, client_id: REACT_APP_CLIENT_KEY, client_secret: REACT_APP_CLIENT_SECRET, } const header = { clientId: REACT_APP_CLIENT_KEY, } await refreshTokenApi(params, header).then(res => { if (res?.success == true) { sessionStorage.setItem('Authorization', res?.data?.value); // sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value); sessionStorage.setItem('scope', res?.data?.scope); history.push('/redirect'); } }) } const handleSubmit = async (values: any) => { await ZjfakeAccountLogin({ ...values, tmpToken }).then((res) => { if (res?.success) { if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) { refreshToken(res?.data) } else { sessionStorage.setItem('Authorization', res?.data?.value); // sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value); sessionStorage.setItem('scope', res?.data?.scope); history.push('/redirect'); } } changeCaptcha(); }); }; const onChange = (key: string) => { if (key == '2') { BrowserType(); InitMedia(); } else { if (allowedToFaceLogin()) { if (whetherIE.current) { releaseCamera('faceLoginFrame'); } else { mediaStreamTrack.current?.stop(); } } } }; const releaseCamera = (id: string) => { const childFrameObj = document.getElementById(id); childFrameObj?.contentWindow?.postMessage('releaseCamera', '*'); } const hanleFaceSubmit = async (multipartFiles: any, values: any) => { let userName = form2.getFieldValue('userName'); if (whetherIE.current) { if (!multipartFiles) { const childFrameObj = document.getElementById('faceLoginFrame'); childFrameObj.contentWindow.postMessage('capture', '*'); } else { await ZjfakeFaceLogin({ userName, multipartFiles }).then((res) => { if (res?.success) { if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) { refreshToken(res?.data) } else { releaseCamera('faceLoginFrame'); sessionStorage.setItem('Authorization', res?.data?.value); sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value); sessionStorage.setItem('scope', res?.data?.scope); history.push('/redirect'); } } }) .finally( () => { setSubmitLoading(false); } ); } } else { if (!multipartFiles) { 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) { hanleFaceSubmit(result, null); }) } else { setSubmitLoading(true); await ZjfakeFaceLogin({ userName, multipartFiles }).then((res) => { if (res?.success) { if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) { refreshToken(res?.data) } else { mediaStreamTrack.current?.stop(); sessionStorage.setItem('Authorization', res?.data?.value); sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value); sessionStorage.setItem('scope', res?.data?.scope); history.push('/redirect'); } } }) .finally( () => { setSubmitLoading(false); } ); } } } const handleOk = () => { // 确定修改密码 if (changeForm.getFieldValue("newPassword") !== changeForm.getFieldValue("newPassword1")) { message.warn('两次密码输入不一致,请重新输入') } else { changeForm.validateFields().then(res => { setSping(true); const date = { identityCard: changeForm.getFieldValue("identityCard"), oldPassword: changeForm.getFieldValue("oldPassword"), newPassword: changeForm.getFieldValue("newPassword"), }; changePass({ ...date }).then(res => { if (res.success) { setSping(false); setIsModalVisible(false) message.success('修改密码成功'); changeForm.resetFields() } else { setSping(false); } }).finally(() => { setSping(false); });; }) } } //浏览器类型 const BrowserType = () => { //取得浏览器的userAgent字符串 var userAgent = navigator.userAgent; //判断是否IE<11 var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE的Edge浏览器 var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE11 var isIE11 = userAgent.indexOf("Trident") > -1 && userAgent.indexOf("rv:11.0") > -1; if (isIE) { var reIE = new RegExp("MSIE(\\d+\\.\\d+);"); reIE.test(userAgent); var fIEVersion = parseFloat(RegExp["$1"]); if (fIEVersion == 7) { return 7; } else if (fIEVersion == 8) { return 8; } else if (fIEVersion == 9) { return 9; } else if (fIEVersion == 10) { return 10; } else { //IE版本<=7 return 6; } } else if (isEdge) { return 'edge'; } else if (isIE11) { //IE11 whetherIE.current = true; return 11; } else { //不是IE浏览器 return -1; } } //初始化video const InitMedia = () => { if (!whetherIE.current) { InitUserMedia({ video: { width: 480, height: 320 } }, success, error); } }; //访问用户媒体设备的兼容方法 const InitUserMedia = (constraints: any, success: any, error: any) => { 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) { //firfox浏览器 navigator.mozGetUserMedia(constraints, success, error); } else if (navigator.getUserMedia) { //旧版API navigator.getUserMedia(constraints, success, error); } } //调用媒体设备成功回调方法 const success = (stream: any) => { var result = stream.getVideoTracks().some(function (track: any) { return track.enabled && track.readyState === 'live'; }); if (result) { //兼容webkit核心浏览器 const CompatibleURL = window.URL || window.webkitURL; //将视频流设置为video元素的源 console.log(stream); //video.src = CompatibleURL.createObjectURL(stream); video.current.srcObject = stream; mediaStreamTrack.current = stream.getTracks()[0]; video.current.play(); } } //调用媒体设备失败回调方法 const error = (error: any) => { message.warn('无法获取到摄像头权限,请确认是否存在摄像头及是否授权使用摄像头'); console.log(`访问用户媒体设备失败${error.name}, ${error.message}`); } //base64转blob const base64ToBlob = (base64: string) => { const parts = base64.split(";base64,"); const contentType = parts[0].split(":")[1]; const raw = window.atob(parts[1]); const rawLength = raw.length; const uInt8Array = new Uint8Array(rawLength); for (let i = 0; i < rawLength; i += 1) { uInt8Array[i] = raw.charCodeAt(i); } return new Blob([uInt8Array], { type: contentType }); }; const IELiveDetectFinish2 = async(data:any) => { console.log(data); setAction(4); hanleFaceSubmit(data, null); } //IELiveDetectFinish const IELiveDetectFinish = async (data: any) => { if(data.code != 0){ console.log(data); setAction(4); hanleFaceSubmit(data.file.file, null); }else{ message.error('活体检测失败'); setSubmitLoading(false); } } const UpdateDetectStatus = async(action:number, timer:number)=>{ setSubmitLoading(true); setAction(action); setTimer(timer); } //是https或者是本地 const httpsOrLocal = () => { let protocol = document.location.protocol; if (protocol == 'https:') { return true; } else { let host = window.location.hostname; if (host == '127.0.0.1' || host == 'localhost') { return true; } } return false; } //是否允许人脸登录 const allowedToFaceLogin = () => { let browseType = BrowserType() if ((browseType == 11 || browseType == -1) && httpsOrLocal()) { return true; } return false; } useEffect(() => { cookie.remove('mall3_token'); sessionStorage.clear(); changeCaptcha(); if (!allowedToFaceLogin()) { setFaceLoginDisable(true); } }, []); return (

中国联通智慧供应链平台 | 招标采购中心

} placeholder="请输入用户名" /> } placeholder="请输入密码" /> } placeholder="请输入验证码" /> changeCaptcha()} src={imgUrl} /> {/* 记住密码 */}
} placeholder="请输入用户名" /> {/* 加载摄像头 */} {/* */} {!whetherIE.current ? () : ()} {/* */} {/* onClick={() => {hanleFaceSubmit(null, null);}} */}
setIsModalVisible(false)} footer={[ , ]} width={600} >
{ const oNumber = new RegExp(/\d/); const oLetter = new RegExp(/[a-zA-Z]/); const oSpecial = '.~!@#$%^&*()_+=-{}|:<>?,./[]-;\\"'; if (!value) { callback('请输入新密码'); return; } if (value.length < 6) { callback('密码不能小于六位,至少含字母、数字、特殊字符其中的2种!'); return; } try { [...value].forEach(val => { if ( !( oNumber.test(val) || oLetter.test(val) || oSpecial.indexOf(val) >= 0 ) ) { throw new Error(); } }); } catch (e) { callback('密码不能小于六位,至少含字母、数字、特殊字符其中的2种!'); } const contain: boolean[] = []; [...value].forEach(val => { if (oNumber.test(val)) { contain[0] = true; } if (oLetter.test(val)) { contain[1] = true; } if (oSpecial.indexOf(val) >= 0) { contain[2] = true; } }); if (contain.filter(item => item === true).length < 2) { callback('密码不能小于六位,至少含字母、数字、特殊字符其中的2种!'); return; } callback(); } } ]} // rules={[ // { // required: true, // message: '请输入新密码', // }, // ]} >
); }; export default Index;