【问题标题】:String representation of an ipv6 address in Classic ASP经典 ASP 中 ipv6 地址的字符串表示
【发布时间】:2021-01-16 12:11:53
【问题描述】:

出于地理定位的目的,我正在尝试获取 ip v6 地址的数值的字符串表示形式。 因为 Classic ASP 不处理 bigint 值,所以我正在尝试使用 Javascript 函数来解决它。

基于这个使用 biginteger.js 库的工作小提琴:https://jsfiddle.net/adamish/mrx3880p/,我调整了该库以作为 ASP 的有效包含。

var ip = '2a00:85c0:0001:0000:0000:0000:0241:0023';


// simulate your address.binaryZeroPad(); method
var parts = [];
ip.split(":").forEach(function(it) {
    var bin = parseInt(it, 16).toString(2);
    while (bin.length < 16) {
        bin = "0" + bin;
    }
    parts.push(bin);
})
var bin = parts.join("");

// Use BigInteger library
var dec = bigInt(bin, 2).toString();
console.log(dec);

Fiddle 中的代码将 ipv6 转换为其二进制表示,然后调用 toString 函数,请求以基数 2 进行转换。

它在小提琴中工作。但是,我无法让它在我的代码中工作,因为返回值是科学计数法,这对我不利。

目标是输入字符串“2a00:85c0:1::241:23”(或其非缩短版本,“2a00:85c0:0001:0000:0000:0000:0241:0023”,不问题)并输出数字等价物的字符串表示形式,或“55830288595252163998698714105846497315”。

由于我只能在 Classic ASP 中使用什么,有没有人能告诉我如何让这种转换工作?

【问题讨论】:

  • 那么您的经典 ASP 代码是什么样的?您在 Classic ASP 中使用 JScript 吗?
  • 您不能只是将 JavaScript 库转换为 JScript 包含文件并期望它能够工作,这取决于 JavaScript 库的现代程度将决定它在转换时工作的可能性。自己试了一下,第 24 行的包含错误:BigInteger.prototype = Object.create(Integer.prototype);,错误为Object doesn't support this property or method
  • 我的 ASP 代码基本上只是对您在我的示例中看到的 javascript 的调用,转换为 .js 包含文件中的函数。我知道,Classic ASP 中的 jscript 支持远没有“真正的”javascript 那样扩展,这就是我的问题的重点:有谁知道我如何使用我拥有的武器来完成这项工作?跨度>
  • 也许你可以使用两个字段。请记住,您的 IPv6 寻址确实将使用 /64 网络,因此您可以使用 64 位网络字段和 64 位 IID 字段。假设您有可用的无符号 64 位整数。
  • 谢谢,罗恩莫平。如果我想保留 ipv6 地址的日志,这将起作用,但不幸的是,在这种情况下,我真的需要十进制表示来匹配 ip2location 提供的范围内的它。

标签: javascript asp-classic ipv6


【解决方案1】:

很遗憾,您将无法执行此操作,因为 VBScript 和 JScript 无法处理所需的数值精度。

这是我在 VBScript 中的第一次尝试

<%
Option Explicit
Const base = 65536
Dim ipv6: ipv6 = "2a00:85c0:0001:0000:0000:0000:0241:0023"
Dim pwr: pwr = 8
Dim hextets: hextets = Split(ipv6, ":")
Dim hextet, ipnum
If IsArray(hextets) Then
  For Each hextet In hextets
    pwr = pwr - 1
    ipnum = ipnum + ((base^pwr) * CLng("&h" & hextet))
  Next
End If
%>
<!doctype html>
<html>
  <head>
    <title>IPv6 to IP Number</title>
  </head>

  <body>
    <pre><%= ipv6 %></pre>
    <pre><%= FormatNumber(ipnum, 0, -2, -2, false) %></pre>
  </body>
</html>

输出:

2a00:85c0:0001:0000:0000:0000:0241:0023
55830288595252200000000000000000000000

这里的问题是计算是正确的,但是数字不能处理精度,所以当它达到最大值时,它默认为0

我的下一个尝试是 JScript(不是我最擅长的语言)

<% @Language = "JScript" %>
<%
var base = 65536;
var ipv6 = "2a00:85c0:0001:0000:0000:0000:0241:0023";
var pwr = 8;
var hextets = ipv6.split(":");
var ipnum;

for (var hextet in hextets) {
  pwr--;
  ipnum += (Math.pow(base, pwr) * parseInt("0x" + hextets[hextet]));
};
%>
<!doctype html>
<html>
  <head>
    <title>IPv6 to IP Number</title>
  </head>

  <body>
    <pre><%= ipv6 %></pre>
    <pre><%= ipnum %></pre>
  </body>
</html>

输出:

2a00:85c0:0001:0000:0000:0000:0241:0023
-1.#IND

这次它以-1.#IND conversion error 失败,这基本上意味着数字太大而无法表示。

因此,虽然不能直接在 VBScript 或 JScript 中使用,但您仍然可以使用另一种语言(C#、VB.Net 等)构建一个 COM 公开类,该类进行计算并生成一个 VBScript / Jscript 可以显示的字符串。


有用的链接

【讨论】:

    【解决方案2】:

    我删除了我之前的答案,因为它不是很有帮助。已经确定您不能使用 Classic ASP 将 IPv6 地址转换为使用 VBscript 的数值。 JScript 可能是可能的,但似乎不太可能。

    我还在高流量经典 ASP 网站上转换和记录 IPv4/6 数值以用于地理定位。

    对于 IPv4,使用 VBscript 转换非常简单:

    Function IPv4ToNumber(ByVal IPv4)
    
        Dim i, Pos, PrevPos, Num
    
        For i = 1 To 4
    
            Pos = InStr(PrevPos + 1, IPv4, ".", 1)
            If i = 4 Then pos = Len(IPv4) + 1
            Num = Int(Mid(IPv4, PrevPos + 1, Pos - PrevPos - 1))
            PrevPos = Pos
            IPv4ToNumber = ((Num Mod 256) * (256 ^ (4 - i))) + IPv4ToNumber
    
        Next
    
    End function
    

    这是另一个有用的 VBscript 函数,它返回 IP 的类型(IPv4、IPv6 或无效 IP 的空字符串)。你可以使用InStr():

    . = IPv4

    : = IPv6

    但此函数使用正则表达式来正确验证 IP 地址:

    Function IP_Type(ByVal IP)
    
        IP_Type = "" ' Default
        
        ' Check for valid IPv4 and IPv6 addresses
        
        Dim IP_RegExp
        
        If Len(IP) >= 7 AND Len(IP) <= 15 Then
        
            ' Potential IPv4
            
            Set IP_RegExp = New RegExp
            
                IP_RegExp.Pattern = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
                IP_Type = IP_RegExp.Test(IP)
                
                If IP_Type Then IP_Type = "IPv4" Else IP_Type  = ""
            
            Set IP_RegExp = Nothing
        
        ElseIf Len(IP) > 15 AND Len(IP) <= 39 Then
        
            ' Potential IPv6
            
            Set IP_RegExp = New RegExp
            
                IP_RegExp.Pattern = "^(([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]))$"
                IP_Type = IP_RegExp.Test(IP)
                
                If IP_Type Then IP_Type = "IPv6" Else IP_Type  = ""
            
            Set IP_RegExp = Nothing
        
        End If
        
    End Function
    

    对于 IPv6,我使用 MySQL 来计算数值。这是一个简单的 SELECT 示例:

    SELECT CAST(
        CONV(
            SUBSTR(
                HEX(
                    INET6_ATON('2a00:85c0:0001:0000:0000:0000:0241:0023')
                )
            ,1,16)
        ,16,10
    )AS DECIMAL(65))
    *18446744073709551616
    +CAST(
        CONV(
            SUBSTR(
                HEX(
                    INET6_ATON('2a00:85c0:0001:0000:0000:0000:0241:0023')
                )
            ,17,16)
        ,16,10
    ) AS DECIMAL(65)) AS ipv6_num;
    

    输出:55830288595252163998698714105846497315(使用完整或缩短的 IPv6 地址)

    它也适用于 MariaDB。对于其他 SQL 平台,逻辑是相同的,但语法和函数可能需要替换为等价物。

    如果您出于地理定位目的记录 IP 数值,那么显然您使用的是数据库,因此将上述 MySQL 代码改编为其他 SQL 平台是我能提供的最佳解决方案。

    我还查找了数字 API 的 IP(免费或基于订阅),但似乎没有(IPv6 仍然非常罕见,因此调用 REST API 可能是一种可能的解决方案)。希望有一个使用 JScript 的解决方案,或者如前所述,您可以使用 COM DLL(我有这方面的经验,我使用 C# 创建了许多 COM DLL,用于在我的 GitHub page 上的经典 ASP 应用程序中使用。您将不过需要 root 访问权限。我使用的是新笔记本电脑,因此需要重新安装 Visual Studio,但我会在有时间时为 IP 创建一个 COM DLL 到数值)。

    【讨论】:

    • OP 询问的是经典 ASP 中的 IPv6 转换,而不是 IPv4。但是,其他一些想法也有其优点。不确定上述建议中有多少只是重申了已经说过的话。
    • 在经典的 asp、vbscript 或 jscript 中是不可能的。我提供了一个数据库替代方案,我认为这是有效的。
    • 那部分是的,无论如何,但其余部分几乎是对我现有答案的评论。
    猜你喜欢
    • 2016-06-12
    • 1970-01-01
    • 2010-12-23
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多