按IP(IPv4,IPv6)获取国家/地区位置

时间:2013-10-16 16:59:51

标签: mysql coldfusion ipv6 ipv4

我一直在测试一些代码,这些代码可以阻止来自特定国家/地区的用户的广告和视频。这不是什么新鲜事,当然不应该很难做到,但我无法解决它与IPv6地址一起工作,因为我不知道如何处理这些。我使用的数据库http://db-ip.com/db/最初看起来像这样:

enter image description here

将两个IP列值转换为二进制并将所有内容移动到新表后,我有:

enter image description here

这是测试代码(当我将其整理出来时,我将使用cfc和存储过程代替):

<!--- manualy change IPs to check if the code works --->
<cfset ipaddress="1.0.127.255">
<cfset ipToArray = listToArray(ipaddress,".")>
<cfset ipBinary= (ipToArray[1] * (256)^3) + (ipToArray[2] * (256)^2) + (ipToArray[3] * 256) + ipToArray[4]>

<cfquery name="getCountry" datasource="mydatabase">
SELECT country
FROM dbip_lookup 
WHERE #ipBinary# >= bin1 AND #ipBinary# <= bin2
</cfquery>

<cfoutput>#getCountry.country#</cfoutput>

正如您所看到的,没有什么太可能只是一个适用于IPv4的简单测试代码:) 我应该以某种方式将IPv6转换为二进制以使其工作吗?如果是这样,该怎么做或是否有其他方法来实现相同的功能?我真的不知道从哪里开始:(

编辑 - 逐步过程

使用网站代码创建数据库表(csv文件中不存在addr_type,因此我删除了列以便能够正确导入csv)

CREATE TABLE `dbip_lookup` (
`ip_start` varbinary(16) NOT NULL,
`ip_end` varbinary(16) NOT NULL,
`country` char(2) NOT NULL,
PRIMARY KEY (`ip_start`)
);

成功创建表后尝试填充数据

LOAD DATA INFILE 'C:/dbip-country.csv' 
INTO TABLE dbip_lookup2 
FIELDS TERMINATED BY ',' 
ENCLOSED BY '"' 
LINES TERMINATED BY '\r\n'

未能抛出以下错误消息“10:07:52 LOAD DATA INFILE'C:/dbip-country.csv'INTO TABLE dbip_lookup2 FIELDS TERMINATED BY','enclOSED by'''LINES INATED IN'\ r \ n '错误代码:1406。第158131行19.641秒列'ip_end'的数据太长 “158131行是IPv6地址的起始位置。

将两个varbinary列修改为(50)mysql成功创建并使用上面的代码填充表。

enter image description here

你的一些简化的cfm代码(它无论如何都不起作用)

<cfset InetAddress = createObject("java", "java.net.InetAddress")>
<cfset addrStart = InetAddress.getByName("2001:0db8:85a3:08d3:1319:8a2e:0370:7344").getAddress()>

<!--- for MySQL.  Use TOP 1 for SQL Server --->
<cfquery name="qResult">
select country from dbip_lookup2
where ip_start <= "#addrStart#"
</cfquery>

<cfoutput>#qResult.country#</cfoutput>

触发自定义错误处理程序:

enter image description here

第43行是WHERE子句开始的地方

1 个答案:

答案 0 :(得分:0)

通过查看PHP中的sample look up code,可以将逻辑移植到这样的内容,以便在CF中查找IPv6,而无需转换为新表:

<cfset InetAddress = createObject("java", "java.net.InetAddress")>
<cfset addrStart = 
  InetAddress.getByName("2001:0db8:85a3:08d3:1319:8a2e:0370:7344").getAddress()>

<!--- for MySQL.  Use TOP 1 for SQL Server --->
<cfquery name="qResult">
  select * from dbip_lookup
  where addr_type = 'ipv6' and 
    ip_start <= <cfqueryparam value="#addrStart#" type="CF_SQL_VARBINARY">
    order by ip_start desc limit 1
</cfquery>

我没有试过这个,希望你能让它发挥作用。

修改

您必须对<cfqueryparam>使用addrStart,因为CF无法将二进制数组转换为##的字符串并以SQL身份发送。如果仍然无效,请考虑使用BinaryEncode()转换为十六进制。