如何用Node.js Net模块实现字符模式输入而非行模式输入?
实现Telnet/TCP服务器的实时密码输入隐藏(替换为
*) 要解决这个问题,核心是让客户端终端切换到字符模式(逐键发送输入),并关闭本地回显,由服务器控制输入的显示逻辑。默认Telnet采用行模式,只有按下回车才会把数据发送给服务器,所以需要通过Telnet协议协商调整行为。
解决方案代码
const Net = require('net'); // Telnet协议指令常量 const IAC = 0xff; // 交互命令起始标记 const WILL = 0xfb; // 表示愿意启用某选项 const DO = 0xfd; // 请求对方启用某选项 const ECHO = 0x01; // 回显控制选项 const SUPPRESS_GO_AHEAD = 0x03; // 抑制前进选项(用于切换字符模式) const server = Net.Server(); server.on('connection', (socket) => { let password = ''; let isProcessingTelnetCmd = false; let telnetCmdBuffer = []; // 发送Telnet协商指令:要求客户端切换字符模式,由服务器控制回显 socket.write(Buffer.from([IAC, DO, SUPPRESS_GO_AHEAD])); socket.write(Buffer.from([IAC, WILL, ECHO])); socket.write('Password: '); socket.on('data', (data) => { for (const byte of data) { // 处理Telnet协商指令,跳过无关的控制包 if (isProcessingTelnetCmd) { telnetCmdBuffer.push(byte); if (telnetCmdBuffer.length === 2) { isProcessingTelnetCmd = false; telnetCmdBuffer = []; } continue; } if (byte === IAC) { isProcessingTelnetCmd = true; continue; } // 处理实际输入字符 switch (byte) { case 0x0d: // 回车符 case 0x0a: // 换行符 socket.write('\n'); console.log('用户输入的密码:', password); // 此处可添加密码验证逻辑 password = ''; socket.write('Password: '); break; case 0x7f: // 退格键(ASCII DEL) if (password.length > 0) { password = password.slice(0, -1); // 发送退格+空格+退格,清除终端上的一个`*` socket.write('\x08 \x08'); } break; default: // 只处理可打印ASCII字符 if (byte >= 0x20 && byte <= 0x7e) { password += String.fromCharCode(byte); // 回显`*`替代输入字符 socket.write('*'); } break; } } }); socket.on('end', () => { console.log('连接已断开'); }); }); server.listen(3000, () => { console.log('服务器监听在 127.0.0.1:3000'); });
关键逻辑说明
- Telnet协商:通过发送
IAC DO SUPPRESS_GO_AHEAD让客户端切换到字符模式(逐键发送输入),IAC WILL ECHO告知客户端由服务器控制回显,禁止客户端本地显示输入内容。 - 逐字符处理:遍历收到的每个字节,过滤Telnet控制指令,只处理实际的输入字符。
- 退格兼容:处理用户退格操作时,同步删除密码缓存的最后一位,并通过终端控制序列清除界面上的一个
*,保证显示与实际输入一致。 - 输入收尾:用户按下回车时,服务器输出完整密码,重置缓存并重新提示输入。
可选变体方案
- 完全无显示输入:如果不需要显示密码长度,直接删除回显
*的代码即可,用户输入时终端无任何反馈,仅服务器能看到完整密码。 - 适配特殊终端:针对Windows Cmd自带的Telnet等特殊客户端,可额外添加ANSI终端控制序列处理,但上述代码已覆盖绝大多数标准Telnet客户端场景。
内容的提问来源于stack exchange,提问作者jji05
相关产品推荐
相关产品推荐

