You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

434 lines
15 KiB
Vue

<template>
<div>
<el-container class="common-layout">
<el-row style="width: 100%; display: flex; justify-content: center;">
<el-col :span="9" class="left">
</el-col>
<el-col :span="15" class="right">
<div class="right_top">
<div>
<el-switch v-model="isDark" inline-prompt active-color="var(--el-fill-color-dark)"
inactive-color="var(--el-color-primary)" active-action-icon="Moon"
inactive-action-icon="Sunny" @change="toggleDark" />
</div>
</div>
<el-form v-if="!UseErweima && !UseUkey" style="width: 400px;" ref="ruleFormRef" status-icon class="demo-ruleForm">
<el-form-item>
<span style="font-size: 22px;">登录您的账户</span>
</el-form-item>
<el-form-item>
<el-input v-model.number="username" :prefix-icon="User" placeholder="用户名" size="large" />
</el-form-item>
<el-form-item>
<el-input v-model="pwd" type="password" autocomplete="off" placeholder="密码" size="large"
:prefix-icon="Lock" />
</el-form-item>
<el-form-item>
<el-button style="width: 100%;" type="primary" @click="login(ruleFormRef)"
size="large">登录</el-button>
</el-form-item>
<el-form-item>
<el-button style="width: 48%;" @click="usePhone()" size="large"
:icon="Iphone"></el-button>
<el-button style="width: 48%;" @click="useUkey()" size="large"
:icon="Key" type="danger">证书登录</el-button>
</el-form-item>
<div style="height: 160px;"></div>
</el-form>
<el-form v-if="UseErweima" style="width: 400px;" status-icon class="demo-ruleForm erweima">
<el-form-item>
<span style="font-size: 22px;">请扫描二维码登录</span>
</el-form-item>
<div class="erweima_tu" v-loading="erweima_loading">
<canvas v-if="seconds>0" id="canvas" width="300" height="300" style="min-height: 300px;min-width: 300px;"></canvas>
<div v-else class="timeout" @click="refresh()">{{erweimaErrMsg}}
<div><RefreshRight style="height: 60px;width: 60px;"></RefreshRight></div>
</div>
</div>
<el-form-item>
<el-button style="width: 100%;" @click="UseErweima=false;seconds=0" size="large">返回账号密码</el-button>
</el-form-item>
<div style="height: 160px;"></div>
</el-form>
<el-form v-if="UseUkey" id="form_xtx" name="form_xtx" style="width: 400px;" status-icon class="demo-ruleForm erweima">
<el-form-item>
<span style="font-size: 22px;">证书登录</span>
</el-form-item>
<el-form-item>
<el-select v-model="selectedZhengShuId" placeholder="请选择证书" size="large" style="width: 100%;">
<el-option v-for="(item,index) in ZhengShuList" :key="index" :label="item.name"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-input v-model="uke_pwd" type="password" autocomplete="off" placeholder="密码" size="large"
:prefix-icon="Lock" />
</el-form-item>
<el-form-item>
<el-button style="width: 100%;" @click="ukeyLogin()" type="danger" size="large">登录</el-button>
</el-form-item>
<el-form-item>
<el-button style="width: 100%;" @click="UseUkey=false;" size="large">返回账号密码</el-button>
</el-form-item>
<div style="height: 160px;"></div>
</el-form>
<div class="right_bottom"></div>
</el-col>
</el-row>
</el-container>
</div>
</template>
<script setup>
import {
Login,addSignJob,XTSignCheckNotify,UkeyGetServeInfo,UkeyUserInfoLogin
} from "@/api/api.js";
import QRCode from 'qrcode'
import {
ElMessage, ElMessageBox
} from 'element-plus'
import {
ref
} from 'vue'
import {
Lock,
User,
Iphone,RefreshRight,Key
} from '@element-plus/icons-vue'
import {
useToggle
} from '@vueuse/shared'
import {
useDark
} from "@vueuse/core";
import CryptoJS from 'crypto-js';
const erweima_loading=ref(false)
const UseErweima=ref(false) //是否使用二维码
const UseUkey=ref(false) //是否使用Ukey
const isDark = useDark()
const toggleDark = () => useToggle(isDark)
let username = ref('')
let pwd = ref('')
const hunxiao=(str)=>{
let originalString =str
var charMap = {
'a': 'z', 'b': 'y', 'c': 'x', 'd': 'w', 'e': 'v',
'f': 'u', 'g': 't', 'h': 's', 'i': 'r', 'j': 'q',
'k': 'p', 'l': 'o', 'm': 'n', 'n': 'm', 'o': 'l',
'p': 'k', 'q': 'j', 'r': 'i', 's': 'h', 't': 'g',
'u': 'f', 'v': 'e', 'w': 'd', 'x': 'c', 'y': 'b',
'z': 'a',
'0': '@', '1': '!', '2': '#', '3': '$', '4': '%',
'5': '^', '6': '&', '7': '*', '8': '(', '9': ')'
};
var mappedString = originalString.split('').map(char => charMap[char] || char).join('');
// 第二步:反转字符串
var reversedString = mappedString.split('').reverse().join('');
// 第三步:添加固定前缀和后缀
var prefixedSuffixString = 'a5331_' + reversedString + '_a454d';
// 第四步:使用 btoa 函数执行 Base64 编码
var encodedString = btoa(prefixedSuffixString);
return encodedString;
}
let login = () => { //登录
if (username.value == '' || pwd.value == '') return ElMessage.error('用户名和密码不能为空')
let data = { //传参
username: username.value,
password:pwd.value ,
}
//调用登录接口
Login(data).then(res => {
if (res.data.status == 'ok') {
sessionStorage.setItem('token', res.data.token);
sessionStorage.setItem('refreshToken', res.data.refresh_token);
// sessionStorage.setItem('tk', JSON.stringify(res.data.tk));
var token = sessionStorage.getItem('token');
if (token == res.data.token) {
if(res.data.pwd_default != undefined && res.data.pwd_default==true){
ElMessageBox.alert('请到"个人中心"修改您的密码', '提示', {
confirmButtonText: '知道了',
callback:action=> {
window.location.href = "./#/dashboard"
}
})
}else{
window.location.href = "./#/dashboard"
}
}
} else {
ElMessage.error(res.data.msg)
}
})
}
const refresh=()=>{
usePhone()
}
let erweimaErrMsg=ref('扫描超时,点击刷新');
let signJobId=ref('');////签名任务id
let qrcode=ref('');
//使用二维码登录
const usePhone=()=>{
clearInterval(timer);
signJobId.value=''
qrcode.value=''
seconds.value=timelength
erweima_loading.value=true
UseErweima.value=true
addSignJob({}).then(res => {
if(res.status){
qrcode.value = JSON.stringify(JSON.parse(res.data.qrCode));
signJobId.value=res.data.signDataId;
console.log(qrcode.value )
var canvas = document.getElementById("canvas");
// 调用函数去生成二维码,参数依次为:二维码的容器、要生成的内容、回调函数
QRCode.toCanvas(canvas,qrcode.value, function(error) {
if (error) {
console.error(error);
} else {
erweima_loading.value=false
start_time()
console.log("success!");
}
})
}else{
ElMessage.error(res.msg)
}
})
}
//定时60秒倒计时
let timelength=60
let seconds = ref(0);
seconds.value=timelength
let pinlv=5 //频率/秒
let timer
const start_time=()=>{
timer = setInterval(CheckNotify, pinlv*1000);
}
//检查扫码回调结果
const CheckNotify=()=>{
if (seconds.value <= 0) {
console.log("倒计时结束!");
clearInterval(timer);
} else {
console.log(seconds.value + "秒");
XTSignCheckNotify({signJobId:signJobId.value}).then(res=>{
if(res.msg !='暂未回调'){
//如果查到了,则结束定时器
clearInterval(timer);
if(res.status){
sessionStorage.setItem('token', res.data.token);
sessionStorage.setItem('refreshToken', res.data.refresh_token);
// sessionStorage.setItem('tk', JSON.stringify(res.data.tk));
var token = sessionStorage.getItem('token');
if (token == res.data.token) {
window.location.href = "./#/dashboard"
}
}else{
ElMessage.error(res.msg)
erweimaErrMsg.value=res.msg
seconds.value=0
}
}
})
seconds.value=seconds.value-pinlv;
}
}
//证书--------------------------------------------------------------
let ZhengShuList = ref('');
let selectedZhengShuId = ref(''); //选中的id
let uke_pwd=ref('');
const useUkey= ()=>{
UseUkey.value=true
let list = xtxsync.SOF_GetUserList()
console.log('证书列表 SOF_GetVersion', list) //获取证书列表
const arr = list.split('&&&').slice(0, -1);
ZhengShuList.value = arr.map(item => {
const [name, value] = item.split('||');
return {
name,
value
};
});
UkeyGetServeInfoAction()
}
let serverInfo=ref('');
const UkeyGetServeInfoAction=()=>{
UkeyGetServeInfo().then(res=>{
if(res.status){
serverInfo.value=res.data.serve_info
if(serverInfo.value.random && serverInfo.value.signData && serverInfo.value.serverCert){
return true
}else{
return ElMessage.error('获取服务器信息失败')
}
}
})
}
const ukeyLogin=()=>{
if(selectedZhengShuId.value==''){
return ElMessage.error('请选择证书')
}
if(uke_pwd.value==''){
return ElMessage.error('请输入证书密码')
}
console.log(selectedZhengShuId.value);
//获取服务器随机数
let randomStr=xtxsync.GenerateRandom(16);
console.log(randomStr);
//服务器对随机数签名
let randomStrSign=xtxsync.SignedData(selectedZhengShuId.value,randomStr);
console.log(randomStrSign);
//----自己获取的
//var strServerSignedData="MEUCIQCOxI79/PFbZiA+tz+PhejhBX8dQn+IvUhA3J/gxD3TygIgT8sPpdr2OqQPUkBUJ3TzF2UiJMu2/WQbAjbi3FBPMN4="
//var strServerRan = "4sXyN2iip6PeTj3n16iRsA=="
//var strServerCert ="MIIEazCCBBCgAwIBAgIKGhAAAAAAIA/MZDAKBggqgRzPVQGDdTBEMQswCQYDVQQGEwJDTjENMAsGA1UECgwEQkpDQTENMAsGA1UECwwEQkpDQTEXMBUGA1UEAwwOQmVpamluZyBTTTIgQ0EwHhcNMjMwNzAyMTYwMDAwWhcNMjYwNzAzMTU1OTU5WjCBgDELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAiIiMQswCQYDVQQHDAIiIjEPMA0GA1UECgwG5YWo5oC7MRIwEAYDVQQLDAnmtYvor5Xpg6gxGzAZBgNVBAMMEuWFqOaAu+a1i+ivleivgeS5pjEVMBMGA1UEKQwMMTExMTExMjIzMTIzMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEiSiGTJ/XbzT7W+SKm7cOp0KAK6S9ZXKHJqVGDefI4UK0+CaUJGJbjYN1HoSu82/M/VTHQg6VAi37iqXyrwLMqaOCAqswggKnMB8GA1UdIwQYMBaAFB/mz9SPxSIql0opihXnFsmSNMS2MB0GA1UdDgQWBBRYIKlLw6Mb3ggWoOsF8YLiF7q6WzAOBgNVHQ8BAf8EBAMCBsAwgaMGA1UdHwSBmzCBmDBgoF6gXKRaMFgxCzAJBgNVBAYTAkNOMQ0wCwYDVQQKDARCSkNBMQ0wCwYDVQQLDARCSkNBMRcwFQYDVQQDDA5CZWlqaW5nIFNNMiBDQTESMBAGA1UEAxMJY2EyMWNybDMwMDSgMqAwhi5odHRwOi8vdGVzdC5iamNhLm9yZy5jbjo4MDAzL2NybC9jYTIxY3JsMzAuY3JsMB4GCiqBHIbvMgIBAQEEEAwOSkoxMTExMTEyMjMxMjMwYAYIKwYBBQUHAQEEVDBSMCMGCCsGAQUFBzABhhdPQ1NQOi8vb2NzcC5iamNhLm9yZy5jbjArBggrBgEFBQcwAoYfaHR0cDovL2NybC5iamNhLm9yZy5jbi9jYWlzc3VlcjBABgNVHSAEOTA3MDUGCSqBHIbvMgICATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vd3d3LmJqY2Eub3JnLmNuL2NwczARBglghkgBhvhCAQEEBAMCAP8wHAYKKoEchu8yAgEBCAQODAwxMTExMTEyMjMxMjMwHgYKKoEchu8yAgECAgQQDA5KSjExMTExMTIyMzEyMzAfBgoqgRyG7zICAQEOBBEMDzk5ODAwMDEwMDkyNDQ0OTAeBgoqgRyG7zICAQEEBBAMDkpKMTExMTExMjIzMTIzMCcGCiqBHIbvMgIBARcEGQwXMUAyMTUwMDlKSjAxMTExMTEyMjMxMjMwGgYIKoEc0BQEAQQEDgwMMTExMTExMjIzMTIzMBQGCiqBHIbvMgIBAR4EBgwEMTA1MDAKBggqgRzPVQGDdQNJADBGAiEAieGsHBwvSeYSrGlK8OCO73lk2B8xP1Hu2OpuHp8AswICIQC7T5jjMXpNMdYA6zZRO1mU61to9uW4UmRjnIgg6GX6GA=="
//服务器随机数 4sXyN2iip6PeTj3n16iRsA==
//签名后的 值 MEUCIQCOxI79/PFbZiA+tz+PhejhBX8dQn+IvUhA3J/gxD3TygIgT8sPpdr2OqQPUkBUJ3TzF2UiJMu2/WQbAjbi3FBPMN4=
//服务器证书 MIIEazCCBBCgAwIBAgIKGhAAAAAAIA/MZDAKBggqgRzPVQGDdTBEMQswCQYDVQQGEwJDTjENMAsGA1UECgwEQkpDQTENMAsGA1UECwwEQkpDQTEXMBUGA1UEAwwOQmVpamluZyBTTTIgQ0EwHhcNMjMwNzAyMTYwMDAwWhcNMjYwNzAzMTU1OTU5WjCBgDELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAiIiMQswCQYDVQQHDAIiIjEPMA0GA1UECgwG5YWo5oC7MRIwEAYDVQQLDAnmtYvor5Xpg6gxGzAZBgNVBAMMEuWFqOaAu+a1i+ivleivgeS5pjEVMBMGA1UEKQwMMTExMTExMjIzMTIzMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEiSiGTJ/XbzT7W+SKm7cOp0KAK6S9ZXKHJqVGDefI4UK0+CaUJGJbjYN1HoSu82/M/VTHQg6VAi37iqXyrwLMqaOCAqswggKnMB8GA1UdIwQYMBaAFB/mz9SPxSIql0opihXnFsmSNMS2MB0GA1UdDgQWBBRYIKlLw6Mb3ggWoOsF8YLiF7q6WzAOBgNVHQ8BAf8EBAMCBsAwgaMGA1UdHwSBmzCBmDBgoF6gXKRaMFgxCzAJBgNVBAYTAkNOMQ0wCwYDVQQKDARCSkNBMQ0wCwYDVQQLDARCSkNBMRcwFQYDVQQDDA5CZWlqaW5nIFNNMiBDQTESMBAGA1UEAxMJY2EyMWNybDMwMDSgMqAwhi5odHRwOi8vdGVzdC5iamNhLm9yZy5jbjo4MDAzL2NybC9jYTIxY3JsMzAuY3JsMB4GCiqBHIbvMgIBAQEEEAwOSkoxMTExMTEyMjMxMjMwYAYIKwYBBQUHAQEEVDBSMCMGCCsGAQUFBzABhhdPQ1NQOi8vb2NzcC5iamNhLm9yZy5jbjArBggrBgEFBQcwAoYfaHR0cDovL2NybC5iamNhLm9yZy5jbi9jYWlzc3VlcjBABgNVHSAEOTA3MDUGCSqBHIbvMgICATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vd3d3LmJqY2Eub3JnLmNuL2NwczARBglghkgBhvhCAQEEBAMCAP8wHAYKKoEchu8yAgEBCAQODAwxMTExMTEyMjMxMjMwHgYKKoEchu8yAgECAgQQDA5KSjExMTExMTIyMzEyMzAfBgoqgRyG7zICAQEOBBEMDzk5ODAwMDEwMDkyNDQ0OTAeBgoqgRyG7zICAQEEBBAMDkpKMTExMTExMjIzMTIzMCcGCiqBHIbvMgIBARcEGQwXMUAyMTUwMDlKSjAxMTExMTEyMjMxMjMwGgYIKoEc0BQEAQQEDgwMMTExMTExMjIzMTIzMBQGCiqBHIbvMgIBAR4EBgwEMTA1MDAKBggqgRzPVQGDdQNJADBGAiEAieGsHBwvSeYSrGlK8OCO73lk2B8xP1Hu2OpuHp8AswICIQC7T5jjMXpNMdYA6zZRO1mU61to9uW4UmRjnIgg6GX6GA==
var strServerSignedData=serverInfo.value.signData
var strServerRan =serverInfo.value.random
var strServerCert =serverInfo.value.serverCert
var bRet = xtxLogin("form_xtx", selectedZhengShuId.value, uke_pwd.value,strServerCert,strServerRan,strServerSignedData);
console.log(bRet)
if (bRet) {
//如果前端教研成功
console.log('前端校验成功')
UkeyUserInfoLoginAction()
} else {
console.log('ukey登录失败')
}
}
//
const UkeyUserInfoLoginAction=()=>{
var UserCert= document.getElementsByName('UserCert')
var UserSignedData= document.getElementsByName('UserSignedData')
var ukey_userid=xtxsync.GetCertEntity(UserCert[0].value)//获取证书唯一标识
var data={
ukey_userid:ukey_userid,
cliCert:UserCert[0].value ,
sign:UserSignedData[0].value,
oridata:serverInfo.value.random,
}
UkeyUserInfoLogin(data).then(res=>{
if(res.status){
sessionStorage.setItem('token', res.data.token);
sessionStorage.setItem('refreshToken', res.data.refresh_token);
// sessionStorage.setItem('tk', JSON.stringify(res.data.tk));
var token = sessionStorage.getItem('token');
if (token == res.data.token) {
window.location.href = "./#/dashboard"
}
}else{
return ElMessage.error(res.msg)
}
})
}
</script>
<style scoped>
.common-layout {
/* border: 10px solid red; */
width: 100%;
height: 100vh;
}
.common-layout .el-main {
display: flex;
justify-content: center;
align-items: center;
}
.left {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: var(--color-table-th-background);
background-image: url('../assets/loginBackg.png');
background-size: 100%;
background-repeat: no-repeat;
background-position: center center;
}
.right {
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: column;
}
.right_top {
display: flex;
justify-content: flex-end;
width: 100%;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.erweima{
}
.erweima_tu {
width: 300px;
height: 300px;
border: 1px solid #ccc;
margin-left: auto;
margin-right: auto;
margin-bottom: 20px;
text-align: center;
color: coral;
}
.timeout{
margin-top: 40%;
text-align: center;
color: coral;
cursor:pointer;
}
</style>