我正在使用JavaScript使用内置的SubtleCrypto.digest()
函数来生成密码校验和。此函数以promise
对象的形式返回结果,然后将其传递给内联函数,该函数将结果转换为十六进制字节的文本表示形式。问题在于,内联文本转换功能digToHex()
不会更新DOM中的隐藏字段,然后在POST请求中将其提交给服务器。
通过附加在表单按钮上的onclick()
事件调用该函数。它读取用户在表单上键入的密码输入,并将其传递到digestMsg()
函数以生成哈希。
请注意,我知道SHA-1
周围的安全问题。目前,这仅是概念证明。
我已经在控制台和“网络”标签上观察到Chrome开发人员工具中的输出。我还监视了服务器(IOT设备)上的传入请求。提交的值始终为null。 digToHex()
函数似乎正在生成哈希,因为该哈希确实会在控制台选项卡中显示为chk.value
的值。从代码中可以看出,我在digestMsg()
Promise处理程序的内部和外部尝试了赋值和表单提交。
function reboot() {
var msg = document.querySelector('#pwd1').value;
// Test purposes only
var opt = document.querySelector('[name = "opt"]');
var chk = document.querySelector('[name = "chk1"]');
// Test purposes only
digestMsg(msg).then(result=>{
var opt = document.querySelector('[name = "opt"]');
var chk = document.querySelector('[name = "chk1"]');
opt.value = 3;
chk.value = digToHex(result);
// document.querySelector('form').submit();
console.log(opt.value);
console.log(chk.value);
});
// form.submit();
alert("Result: " + opt.value + " - " + chk.value);
}
function digToHex(buf) {
const bytes = new Uint8Array(buf);
const hexCodes = [...bytes].map(value => {
const hexCode = value.toString(16);
const padHexCode = hexCode.padStart(2, '0');
return padHexCode;
});
return hexCodes.join('');
}
function digestMsg(msg) {
const enc = new TextEncoder();
const data = enc.encode(msg);
return window.crypto.subtle.digest('SHA-1', data);
}
如果未注释两行sumbit()
中的任何一条,则服务器上会收到null
值,但Chrome开发人员工具会在控制台输出中显示正确的值。对开发人员工具中的“网络输出”选项卡的进一步调查确认,实际上正在传输空值。我希望看到"opt"
的值为3
和chk1
的值包含哈希值。
这是调用代码的HTML:
<form method="post" action="/admin">
<input name="chk1" value="" hidden/>
<input name="chk2" value="" hidden/>
<input name="opt" value=0 hidden/>
<table>
<tr><th>Current password:</th><td><input id="pwd1" type="password"> </input></input></td>
<tr><th>New password:</th><td><input id="pwd2" type="password"></input></input></td>
<tr><th>Confirm new password:</th><td><input id="pwd3" type="password"></input></input></td>
<tr><th></th><td align="right"><input type="submit" class="btn" value="Change" onclick="change()"/></td></tr>
<tr><th></th><td><br></td></tr>
<tr><th>Defaults</th><td align="right"><input type="submit" class="btn" value="Reset" onclick="reset()"/></td></tr>
<tr><th>Restart WiFi</th><td align="right"><input type="button" class="btn" value="Reboot" onclick="reboot()"/></td></tr>
</table>
</form>
根据Marius进行的进一步测试表明,该代码确实适用于静态html页面。因此,该问题似乎与我为每个表单动态加载html的方式有关。我在下面附加了用于主页(父页面)的html:
<html>
<head>
<meta charset="utf-8">
<title>AR488 WiFi Configuration</title>
<link rel="stylesheet" href="AR488wifi.css">
<script defer src="AR488wifi.js"></script>
</head>
<body onload="getPage('seeStat.html')";>
<div class="mpage">
<div class="headr">AR488 WiFi Configuration</div>
<div>
<ul>
<li id="mStat" class="active"><a onclick="getPage('seeStat.html')">Status</a></li>
<li id="mGen"><a onclick="getPage('cfgGen.div')">General</a></li>
<li id="mWifi"><a onclick="getPage('cfgWifi.div')">WiFi</a></li>
<li id="m488"><a onclick="getPage('cfg488.div')">GPIB</a></li>
<li id="mAdm"><a onclick="getPage('cfgAdm.div')">Admin</a></li>
</ul>
</div>
<hr>
<div id="cfgPage" class="conf">
</div>
<div>
<hr>
<table class="foot"><tr>
<td>AR488 WiFi ver: 0.00.00</td>
<td>Firmware ver: 0.00.00</td>
</tr></table>
</div>
</div>
</body>
</html>
答案 0 :(得分:0)
您的代码似乎正常。我已经复制了您拥有的内容,并添加了一些HTML来模拟这一点。确保未禁用这些字段。
reboot();
function reboot() {
var msg = document.querySelector('#pwd1').value;
// Test purposes only
var opt = document.querySelector('[name = "opt"]');
var chk = document.querySelector('[name = "chk1"]');
// Test purposes only
digestMsg(msg).then(result=>{
var opt = document.querySelector('[name = "opt"]');
var chk = document.querySelector('[name = "chk1"]');
opt.value = 3;
chk.value = digToHex(result);
console.log(opt.value);
console.log(chk.value);
});
}
function digToHex(buf) {
const bytes = new Uint8Array(buf);
const hexCodes = [...bytes].map(value => {
const hexCode = value.toString(16);
const padHexCode = hexCode.padStart(2, '0');
return padHexCode;
});
return hexCodes.join('');
}
function digestMsg(msg) {
const enc = new TextEncoder();
const data = enc.encode(msg);
return window.crypto.subtle.digest('SHA-1', data);
}
<input type="password" id="pwd1" value="test" />
<input type="text" name="opt" />
<input type="text" name="chk1" />
答案 1 :(得分:0)
我相信我已经找到了解决方案!
在我的原始代码中,我使用querySelector()获取对表单对象的引用,该引用立即传递给提交,但在完成 之后:
document.querySelector('form').submit();
提交表单时将“ opt”设置为“ 0”(我专门设置的数字值),而不是null或未定义,因此此命令似乎正在创建对原始未修改表单的引用,然后立即对其进行引用提交。
我进行了尝试,在处理发生之前,在digestMsg()处理程序的上下文中创建了对表单的引用:
var formObj = document.querySelector('form');
在处理完表单并更新值之后,可以使用以下方式提交表单:
formObj.submit();
这一次,表单提交了正确的更新值。调整后的代码(减去各种测试警报)现在看起来像这样:
function reboot() {
var msg = document.querySelector('#pwd1').value;
digestMsg(msg).then(result=>{
var formObj = document.querySelector('form');
var opt = document.querySelector('[name = "opt"]');
var chk = document.querySelector('[name = "chk1"]');
opt.value = 3;
chk.value = digToHex(result);
formObj.submit();
});
}
我想知道为什么第一个命令创建了对原始修改表单的引用,而没有考虑更新后的值?在这两种情况下,事情似乎都以相同的顺序发生-将表单加载到浏览器中,更新值并提交表单。另外,为什么原始版本不能在静态HTML页面上使用但在动态加载的表单上可以使用?如果有人有解释,我会很想听听。
同时,感谢您的有用评论,这些评论帮助我集中精力思考并找到解决方案。
以上只是概念证明,需要进一步验证和调整才能获得实际的工作形式。