【发布时间】:2019-06-25 17:38:09
【问题描述】:
我正在使用 javascript 使用内置的 SubtleCrypto.digest() 函数生成密码校验和。此函数将结果作为promise 对象返回,然后将其传递给内联函数,该函数将结果转换为十六进制字节的文本表示。问题是内联文本转换函数digToHex() 没有更新 DOM 中的隐藏字段,然后在 POST 请求中提交给服务器。
通过附加到表单按钮的onclick() 事件调用该函数。它读取用户在表单上输入的密码,并将其传递给digestMsg() 函数以生成哈希。
请注意,我了解SHA-1 周围的安全问题。目前这只是概念验证。
我在控制台和网络选项卡上观察了 Chrome 开发人员工具中的输出。我还监控了服务器(一个物联网设备)上的传入请求。提交的值始终为空。 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>
【问题讨论】:
-
请显示相应的 HTML。请注意,如果该字段被禁用,则在表单提交期间将不会传递该值。
-
隐藏字段也必须在提交的表单元素中。
-
你是怎么打电话给
reboot的?您是否阻止默认操作 - 在您的承诺填写之前提交表单? -
这不是您创建隐藏字段的方式。它是
<input type="hidden" ... />我猜你有一些 CSS 使用“隐藏”属性并隐藏 DOM 中的字段。 -
我只是从使用 onclick() 事件的按钮控件调用 reboot()。我现在添加了 HTML 来显示这一点。我很欣赏可以将事件处理程序添加到 javascript。
标签: javascript promise