1.什么是ukey
UKey是一种通过USB (通用串行总线接口)直接与计算机相连、具有密码验证功能、可靠高速的小型存储设备。(图片和本段取至百度百科)
2.Ukey的认证流程
1.请求认证服务器拿到随机数
2.响应认证客户端
通过xml格式的数据,请求websocket,使用浏览器activeX控件调出认证客户端
部分代码:
var addr = "ws://127.0.0.1:30318";
var bodyx = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<getsignandtokenreq version=\"1\">" +
"<challenge>" + random + "</challenge>" +
"</getsignandtokenreq> "
// 建立websocket连接
var msWs = new WebSocket(addr)
msWs.onmessage = function (ev) {
// 在这里面去处理
}
3.认证客户端输入口令进行票据认证
输入口令后,这步我们就不用管了,会自动的去去验证是否正确,如果输入错误,返回的xml结构里面大概如下
<xxx>
<result>0</result>
....
</xxx>
可以通过这个<result>
节点去判断是否认证成功
4.认证成功后解密获取认证信息
每个ukey制造商的加密方式都不一样,请阅读制造商提供的文档,下面讲解我用的这个key的加密方式
要经过两次解密,再对最后一次解密获取<dncode>
节点进行字符串截取,可以获取到认证信息,再拿数据库进行对比,再在服务端写一个无密登录即可实现ukey单点登录
解密示例代码
function getUkeyByXml(xml) {
console.log("开始解析xml======")
try {
// 初始化xml解析对象
var xmlObj = new DOMParser();
var xmlDom = xmlObj.parseFromString(xml, "text/xml");
var tokenInfo = xmlDom.getElementsByTagName("tokeninfo")
var s1_code = tokenInfo[0].textContent
// 对第一层数据进行base64转码
var tokenInfoXml = atob(s1_code);
addLog("tokenInfoXml", tokenInfoXml)
var om1 = tokenInfoXml.indexOf("<ticketinfo>");
var om2 = tokenInfoXml.indexOf("</ticketinfo>");
tokenInfoXml = tokenInfoXml.substring(om1, om2) + "</ticketinfo>";
var tokenDom = xmlObj.parseFromString(tokenInfoXml, "text/xml")
var ticketinfo = tokenDom.getElementsByTagName("ticketinfo");
var s2_code = ticketinfo[0].textContent;
// 对第二层数进行base64转码
var userInfoXml = atob(s2_code);
addLog("userInfoXml", userInfoXml)
var userDom = xmlObj.parseFromString(userInfoXml, "text/xml");
var userInfo = userDom.getElementsByTagName("dncode");
addLog("userInfo", userInfo)
var userContent = userInfo[0].textContent
addLog("userContent", userContent)
var ukeyCodeIndex = userContent.indexOf("Identifier=");
var ukeyCode = userContent.substring(ukeyCodeIndex, ukeyCodeIndex + 38 + ("Identifier".length))
addLog("ukeyCode", ukeyCode)
ukeyCode = ukeyCode.replace("Identifier=", "").trim()
console.log("ukeyCode = [" + ukeyCode + "]")
addLog("ukeyCode", ukeyCode)
console.log("解析完成 =========")
return ukeyCode;
} catch (error) {
console.log("解析失败")
return null;
}
}
function addLog(log1, log2) {
$("#login_res").text($("#login_res").text() + "[info] --" + new Date().toLocaleString() + " -- " + log1 + "|" + log2 + "\n")
}
注意,每一家的ukey制造商的解密和流程都不一样,本文仅供要做ukey的小白逻辑参考,不懂的可以私聊哦~