我一直在测试一些代码,这些代码可以让我屏蔽来自特定国家/地区的用户的广告和视频。这不是什么新鲜事,当然应该不难做到,但是我无法解决它以使用 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 转换为二进制文件以使其工作吗?如果是这样,该怎么做,或者是否有其他方法可以实现相同的功能?我真的不知道从哪里开始:(
编辑 - 分步过程
使用来自网站的代码创建数据库表(addr_type 在 csv 文件中不存在,所以我删除了该列以便能够正确导入 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 行 19.641 秒处列 'ip_end' 的数据太长 "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 子句开始的地方
最佳答案
通过查看 sample look up code在 PHP 中,可以将逻辑移植到这样的逻辑中以在 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()
转换为十六进制.
关于mysql - 通过 IP (IPv4,IPv6) 获取国家位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19409338/