简体   繁体   English

为什么此代码中的表单DOM对象值未更新?

[英]Why are the form DOM object values not being updated in this code?

I am using javascript to generate a password checksum using the built-in SubtleCrypto.digest() function. 我正在使用javascript通过内置的SubtleCrypto.digest()函数生成密码校验和。 This function returns the result as a promise object which is then passed to an inline function that converts the result to a text representation of the hex bytes. 该函数以promise对象的形式返回结果,然后将其传递给一个内联函数,该函数将结果转换为十六进制字节的文本表示形式。 The problem is that the inline text conversion function digToHex() is not updating the hidden fields in the DOM which are then submitted to the server in a POST request. 问题在于,内联文本转换函数digToHex()不会更新DOM中的隐藏字段,然后在POST请求中将其提交给服务器。

The function is called via an onclick() event attached to the button on the form. 通过附加在表单按钮上的onclick()事件调用该函数。 It reads the password input typed in by the user on the form and passes that to the digestMsg() function for generating the hash. 它读取用户在表单上键入的密码输入,并将其传递给digestMsg()函数以生成哈希。

Please note that I am aware of the security issues around SHA-1 . 请注意,我知道SHA-1周围的安全问题。 At present this is proof of concept only. 目前,这仅是概念证明。

I have observed the output in Chrome developer tools, both on the console and network tab. 我已经在控制台和网络标签上的Chrome开发者工具中观察到了输出。 I have also monitored the incoming request on the server (an IOT device). 我还监视了服务器(IOT设备)上的传入请求。 The submitted values are always null. 提交的值始终为null。 The digToHex() function seems to be generating a hash because the hash does appear as the value of chk.value in the console tab. digToHex()函数似乎正在生成哈希,因为该哈希确实在控制台选项卡中显示为chk.value的值。 As can be seen from the code, I have tried assignments and form submission both outside and inside the context of the digestMsg() promise handler. 从代码中可以看出,我尝试了digestMsg()承诺处理程序的内部和外部的赋值和表单提交。

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);
}

When either of the two sumbit() lines were uncommented, null values were received on the server but Chrome developer tools shows the correct values on the console output. 如果未注释两条sumbit()行中的任何一条,则服务器上会收到null值,但Chrome开发人员工具会在控制台输出上显示正确的值。 Further investigation of the network output tab in developer tools confirms that null values are actually being transmitted. 对开发人员工具中的“网络输出”选项卡的进一步调查确认,实际上正在传输空值。 I would expect to see "opt" with a value of 3 and chk1 with value containing the hash. 我希望看到"opt"的值为3chk1的值包含哈希值。

This is the HTML that calls the code: 这是调用代码的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>

Further testing as per Marius shows that the code does actually work with a static html page. 根据Marius进行的进一步测试表明,该代码实际上可用于静态html页面。 The problem would therefore appear to be related to the way I am dynamically loading the html for each form. 因此,该问题似乎与我为每个表单动态加载html的方式有关。 I attach the html for the main (parent) page below: 我附上下面的主页(父页面)的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>

Your code seems fine. 您的代码似乎很好。 I've copied what you have and added some HTML to simulate this. 我已经复制了您拥有的内容,并添加了一些HTML来模拟这一点。 Make sure the fields aren't disabled. 确保未禁用这些字段。

 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" /> 

I believe I have found a solution! 相信我已经找到了解决方案!

In my original code I was using querySelector() to obtain a reference to the form object which was immediately passed to submit but after processing was done: 在我的原始代码中,我使用querySelector()获得对表单对象的引用,该引用立即传递给提交,但处理完成之后:

document.querySelector('form').submit();

The form was being submitted with "opt" set to '0' - a numeric value that I had specifically set - not null or undefined, so this command appeared to be creating a reference to the original unmodified form which was then immediately submitted. 提交表单时将“ opt”设置为“ 0”(我专门设置的数字值),而不是null或未定义,因此此命令似乎正在创建对原始未修改表单的引用,然后立即提交该表单。

I experimented by creating a reference to the form in the context of the digestMsg() handler before processing took place with: 我进行了实验, 处理发生之前 ,在digestMsg()处理程序的上下文中创建了对表单的引用:

var formObj = document.querySelector('form');

After processing the form and updating values it was then submitted with: 处理完表单并更新值后,将其提交给:

formObj.submit();

This time, the form submitted with the correct updated values. 这一次,表单提交了正确的更新值。 The adjusted code (minus various test alerts) now looks like this: 调整后的代码(减去各种测试警报)现在看起来像这样:

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();
    });
}

I would be interested to know WHY the first command created a reference to the original modified form and did not take into account the updated values? 我想知道为什么第一个命令创建了对原始修改形式的引用,但未考虑更新值? In both cases things seem to happen in the same order - the form is loaded into the browser, the values are updated and the form is submitted. 在这两种情况下,事情似乎都以相同的顺序发生-将表单加载到浏览器中,更新值并提交表单。 Also, why did the original version did work with a static HTML page but not with a dynamically loaded form? 另外,为什么原始版本不能在静态HTML页面上使用但在动态加载的表单上可以使用? If anyone has an explanation I would be eager to hear it. 如果有人有解释,我会很想听听。

In the meantime, thanks for the helpful comments which have helped me focus my thinking and arrive at a solution. 同时,感谢您的有用评论,这些评论帮助我集中精力思考并找到解决方案。

The above is just proof of concept and further validation and adjustments will be required to achieve an actual working form. 以上仅是概念上的证明,需要进一步的验证和调整才能获得实际的工作形式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM