【问题标题】:Get country location by IP (IPv4,IPv6)通过 IP (IPv4,IPv6) 获取国家/地区位置
【发布时间】:2013-10-24 22:00:32
【问题描述】:

我一直在测试一些代码,这些代码可以让我屏蔽来自特定国家/地区的用户的广告和视频。这不是什么新鲜事,当然也不难做到,但是我无法将其整理出来以使用 IPv6 地址,因为我不知道如何处理这些地址。我使用这个数据库http://db-ip.com/db/,它最初看起来像这样:

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

这里是测试代码(我整理的时候会用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 TERMINATED BY '\r\n ' 错误代码:1406。第 158131 行的 'ip_end' 列的数据太长 19.641 秒 " 158131 行是 IPv6 地址开始的地方。

在将两个 varbinary 列都修改为 (50) 后,mysql 成功创建并使用上述代码填充了表。

你的 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>

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

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

【问题讨论】:

  • db-ip.com/db 确实支持 IPv6,DB 中有很多这样的 :)

标签: mysql coldfusion ipv6 ipv4


【解决方案1】:

通过查看 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>

我还没有尝试过,希望你能用它。

编辑

您必须将&lt;cfqueryparam&gt; 用于addrStart,因为CF 无法使用## 将二进制数组转换为字符串并作为SQL 发送。如果这仍然不起作用,请考虑使用 BinaryEncode() 转换为十六进制。

【讨论】:

  • 不知道如何根据 IPv4 获取国家/地区信息,除非分配了另外两个列!?如何在范围内计数?
  • 我也检查了你的代码,得到“ByteArray objects cannot be converted to strings”这可能是因为我已将 varbinary 更改为 varchar...在网站上创建表格的代码没有工作!
  • 按原样使用数据库,不要更改它,查找代码应按预期工作。如果您使用 MSSQL,请在 db-ip.com/db/#external 使用 ZORAN DB-IP 导入器
  • 您可以添加额外的逻辑来检测IP是v4还是v6,并相应地使用正确的addr_type
  • 是的,我稍后会添加它以及使用 cfc 和存储过程 insted 的测试代码,但是需要让它工作。我用mysql,代码不行!
猜你喜欢
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 2016-02-04
  • 2023-03-21
  • 2012-02-22
  • 2012-01-14
相关资源
最近更新 更多