使用JavaScript脱敏IPv4与IPv6地址的问题求助
IPv6地址脱敏正则匹配失效问题解决
问题概述
搭建包含input和output双textarea的前端页面,需求如下:
- 解析输入文本中的IPv4/IPv6地址
- 用
.replace方法将其脱敏为[IPv4]、[IPv6] - 结果展示在output区域
目前IPv4脱敏功能正常,但IPv6地址存在部分无法匹配替换的情况:最初完全无法匹配,拆分逐行处理后有所改善,但仍有地址遗漏。使用的IPv6正则在第三方测试站可正常匹配,但在JavaScript代码中失效,需纯前端完成修复。
复现代码
<html> <head> </head> <body> <div> <label for="input" class= "left">Input Text</label> <label for="output" class = "right">Obfuscated Text - Click Text to Copy</label> <span></span> <textarea id="input"></textarea> <textarea id="output"></textarea> </div> <br> <button onclick="obfuscate()">Obfuscate</button> <script> function obfuscate() { // Get the input and output textareas var input = document.getElementById("input"); var output = document.getElementById("output"); // Obfuscate the text in the input textarea var obfuscatedText = input.value.replace(/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g, "[IPv4]") var lines = obfuscatedText.split('\n') const modifiedLines = lines.map(line => line.replace(/\b(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\b/,"[IPv6]")); // Set the value of the output textarea to the obfuscated text output.value = modifiedLines.join('\n'); } </script> </body> </html>
测试输入
subnet6 3ffe:501:ffff:100::/64 { # Two addresses available to clients # (the third client should get NoAddrsAvail) range6 3ffe:501:ffff:100::10 3ffe:501:ffff:100::11; # Use the whole /64 prefix for temporary addresses # (i.e., direct application of RFC 4941) range6 3ffe:501:ffff:100:: temporary; # Some /64 prefixes available for Prefix Delegation (RFC 3633) prefix6 3ffe:501:ffff:100:: 3ffe:501:ffff:111:: /64; } # A second subnet behind a relay agent subnet6 3ffe:501:ffff:101::/64 { range6 3ffe:501:ffff:101::10 3ffe:501:ffff:101::11; # Override of the global definitions, # works only when a resource (address or prefix) is assigned option dhcp6.name-servers 3ffe:501:ffff:101:200:ff:fe00:3f3e; }
实际异常输出
subnet6 3ffe:501:ffff:100::/64 { # Two addresses available to clients # (the third client should get NoAddrsAvail) range6 [IPv6]10 3ffe:501:ffff:100::11; # Use the whole /64 prefix for temporary addresses # (i.e., direct application of RFC 4941) range6 3ffe:501:ffff:100:: temporary; # Some /64 prefixes available for Prefix Delegation (RFC 3633) prefix6 3ffe:501:ffff:100:: 3ffe:501:ffff:111:: /64; } # A second subnet behind a relay agent subnet6 3ffe:501:ffff:101::/64 { range6 [IPv6]10 3ffe:501:ffff:101::11; # Override of the global definitions, # works only when a resource (address or prefix) is assigned option dhcp6.name-servers [IPv6]; }
问题原因分析
- 单词边界
\b不适用IPv6地址:\b匹配的是单词字符(字母、数字、下划线)与非单词字符的边界,但IPv6中的冒号、双冒号属于非单词字符,导致像3ffe:501:ffff:100::10这类地址无法被完整匹配,仅匹配到3ffe:501:ffff:100::部分,剩下的10残留。 - 缺少全局匹配标志
g:当前replace未添加g,仅会替换每行第一个匹配到的地址,后续地址不会被处理。
修复方案
修改IPv6匹配正则,替换\b为更精准的空白边界判断,并添加全局匹配标志g:
修改后的完整代码
<html> <head> </head> <body> <div> <label for="input" class= "left">Input Text</label> <label for="output" class = "right">Obfuscated Text - Click Text to Copy</label> <span></span> <textarea id="input"></textarea> <textarea id="output"></textarea> </div> <br> <button onclick="obfuscate()">Obfuscate</button> <script> function obfuscate() { var input = document.getElementById("input"); var output = document.getElementById("output"); // 先处理IPv4 var obfuscatedText = input.value.replace(/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g, "[IPv4]"); // 处理IPv6:替换\b为空白边界判断,添加g标志全局替换 const ipv6Regex = /(?<!\S)(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(?!\S)/g; obfuscatedText = obfuscatedText.replace(ipv6Regex, "[IPv6]"); output.value = obfuscatedText; } </script> </body> </html>
关键修改说明
(?<!\S):断言当前位置前面不是非空白字符,即匹配行首或空白字符后的地址开头(?!\S):断言当前位置后面不是非空白字符,即匹配行尾或空白/标点前的地址结尾- 添加
g标志:实现全局替换,文本中所有匹配的IPv6地址都会被替换 - 移除逐行拆分逻辑:优化为直接全局替换,简化代码同时保证效果
修复后输出效果
subnet6 [IPv6]/64 { # Two addresses available to clients # (the third client should get NoAddrsAvail) range6 [IPv6] [IPv6]; # Use the whole /64 prefix for temporary addresses # (i.e., direct application of RFC 4941) range6 [IPv6] temporary; # Some /64 prefixes available for Prefix Delegation (RFC 3633) prefix6 [IPv6] [IPv6] /64; } # A second subnet behind a relay agent subnet6 [IPv6]/64 { range6 [IPv6] [IPv6]; # Override of the global definitions, # works only when a resource (address or prefix) is assigned option dhcp6.name-servers [IPv6]; }
内容的提问来源于stack exchange,提问作者Kaleb Fenley
相关产品推荐
相关产品推荐

