后台增加IP地理位置显示功能
用户信息表,是大多数系统都有的。我们也知道,通常都会有类似 注册IP 和 最后登录IP 这两个的字段,来存储用户注册时候的IP地址和最后登录的IP的地址。
获取这样的地址,在后台显示 xxx.xxx.xxx.xxx 的地址段,让人看到很不自然,根本就不知道具体地理位置。
现在我们就简单的实现一下这个功能。
用到了 读取纯真IP数据库的公用组件QQWry.NET 这个组件,作者阿不。(谢谢他的共享)
还要去下载最新的纯真IP地址库,下载获得QQWry.dat
最后请出Js中的小靓妞,jquery-1.3.1.js
新建Web项目AjaxIP,将QQWry.dat添加到App_Data下。
然后添加QQWry.NET的组件类,如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.IO;
5 using System.Text.RegularExpressions;
6 using System.Net;
7 using System.Net.Sockets;
8
9 namespace AjaxIP
10 {
11 public class IPLocation
12 {
13 public string IP { get; set; }
14 public string Country { get; set; }
15 public string Local { get; set; }
16 }
17
18 public class QQWryLocator
19 {
20 static Encoding encoding = Encoding.GetEncoding("GB2312");
21
22 private byte[] data;
23 int firstStartIpOffset;
24 int lastStartIpOffset;
25 int ipCount;
26
27 public int Count { get { return ipCount; } }
28
29 public QQWryLocator(string dataPath)
30 {
31 using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
32 {
33 data = new byte[fs.Length];
34 fs.Read(data, 0, data.Length);
35 }
36
37 firstStartIpOffset = (int)data[0] + (((int)data[1]) << 8) + (((int)data[2]) << 16) + (((int)data[3]) << 24);
38 lastStartIpOffset = (int)data[4] + (((int)data[5]) << 8) + (((int)data[6]) << 16) + (((int)data[7]) << 24);
39 ipCount = (lastStartIpOffset - firstStartIpOffset) / 7 + 1;
40
41 if (ipCount <= 1)
42 {
43 throw new ArgumentException("ip FileDataError");
44 }
45 }
46
47 public static uint IpToInt(string ip)
48 {
49 //string[] strArray = ip.Split('.');
50 //return (uint.Parse(strArray[0]) << 24) + (uint.Parse(strArray[1]) << 16) + (uint.Parse(strArray[2]) << 8) + uint.Parse(strArray[0]);
51 //return (uint)IPAddress.HostToNetworkOrder((int)(IPAddress.Parse(ip).Address));
52
53 byte[] bytes = IPAddress.Parse(ip).GetAddressBytes();
54 return (uint)bytes[3] + (((uint)bytes[2]) << 8) + (((uint)bytes[1]) << 16) + (((uint)bytes[0]) << 24);
55 }
56
57 public static string IntToIP(uint ip_Int)
58 {
59 return new IPAddress(ip_Int).ToString();
60 }
61
62 public IPLocation Query(string ip)
63 {
64 IPAddress address = IPAddress.Parse(ip);
65 if (address.AddressFamily != AddressFamily.InterNetwork)
66 {
67 throw new ArgumentException("不支持非IPV4的地址");
68 }
69
70 if (IPAddress.IsLoopback(address))
71 {
72 return new IPLocation() { IP = ip, Country = "本机内部环回地址", Local = string.Empty };
73 }
74
75 uint intIP = (uint)IPAddress.HostToNetworkOrder((int)address.Address);
76
77 //if ((((intIP >= IpToInt("0.0.0.0")) && (intIP <= IpToInt("2.255.255.255"))) || ((intIP >= IpToInt("64.0.0.0")) && (intIP <= IpToInt("126.255.255.255")))) ||
78 //((intIP >= IpToInt("58.0.0.0")) && (intIP <= IpToInt("60.255.255.255"))))
79 //if (intIP <= 50331647 || (intIP >= 1073741824 && intIP <= 2130706431) || (intIP >= 973078528 && intIP <= 1023410175))
80 //{
81 // return new IPLocation() { IP = ip, Country = "网络保留地址", Local = string.Empty };
82 //}
83
84 IPLocation ipLocation = new IPLocation() { IP = ip };
85
86 uint right = (uint)ipCount;
87 uint left = 0;
88 uint middle = 0;
89 uint startIp = 0;
90 uint endIpOff = 0;
91 uint endIp = 0;
92 int countryFlag = 0;
93
94 while (left < (right - 1))
95 {
96 middle = (right + left) / 2;
97 startIp = GetStartIp(middle, out endIpOff);
98 if (intIP == startIp)
99 {
100 left = middle;
101 break;
102 }
103 if (intIP > startIp)
104 {
105 left = middle;
106 }
107 else
108 {
109 right = middle;
110 }
111 }
112 startIp = GetStartIp(left, out endIpOff);
113 endIp = GetEndIp(endIpOff, out countryFlag);
114 if ((startIp <= intIP) && (endIp >= intIP))
115 {
116 string local;
117 ipLocation.Country = GetCountry(endIpOff, countryFlag, out local);
118 ipLocation.Local = local;
119 }
120 else
121 {
122 ipLocation.Country = "未知";
123 ipLocation.Local = string.Empty;
124 }
125 return ipLocation;
126 }
127
128 private uint GetStartIp(uint left, out uint endIpOff)
129 {
130 int leftOffset = (int)(firstStartIpOffset + (left * 7));
131 endIpOff = (uint)data[4 + leftOffset] + (((uint)data[5 + leftOffset]) << 8) + (((uint)data[6 + leftOffset]) << 16);
132 return (uint)data[leftOffset] + (((uint)data[1 + leftOffset]) << 8) + (((uint)data[2 + leftOffset]) << 16) + (((uint)data[3 + leftOffset]) << 24);
133 }
134
135 private uint GetEndIp(uint endIpOff, out int countryFlag)
136 {
137 countryFlag = data[4 + endIpOff];
138 return (uint)data[endIpOff] + (((uint)data[1 + endIpOff]) << 8) + (((uint)data[2 + endIpOff]) << 16) + (((uint)data[3 + endIpOff]) << 24);
139 }
140
141 /// <summary>
142 /// Gets the country.
143 /// </summary>
144 /// <param name="endIpOff">The end ip off.</param>
145 /// <param name="countryFlag">The country flag.</param>
146 /// <param name="local">The local.</param>
147 /// <returns>country</returns>
148 private string GetCountry(uint endIpOff, int countryFlag, out string local)
149 {
150 string country = string.Empty;
151 uint offset = endIpOff + 4;
152 switch (countryFlag)
153 {
154 case 1:
155 case 2:
156 country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
157 offset = endIpOff + 8;
158 local = (1 == countryFlag) ? string.Empty : GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
159 break;
160 default:
161 country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
162 local = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
163 break;
164 }
165 return country;
166 }
167
168 private string GetFlagStr(ref uint offset, ref int countryFlag, ref uint endIpOff)
169 {
170 int flag = 0;
171 while (true)
172 {
173 flag = data[offset];
174 //没有重定向
175 if (flag != 1 && flag != 2)
176 {
177 break;
178 }
179 if (flag == 2)
180 {
181 countryFlag = 2;
182 endIpOff = offset - 4;
183 }
184 offset = (uint)data[1 + offset] + (((uint)data[2 + offset]) << 8) + (((uint)data[3 + offset]) << 16);
185 }
186 if (offset < 12)
187 {
188 return string.Empty;
189 }
190 return GetStr(ref offset);
191 }
192
193 /// <summary>
194 /// 读取字符串...
195 /// </summary>
196 /// <param name="offset"></param>
197 /// <returns></returns>
198 private string GetStr(ref uint offset)
199 {
200 byte lowByte = 0;
201 byte highByte = 0;
202 StringBuilder stringBuilder = new StringBuilder(16);
203 while (true)
204 {
205 lowByte = data[offset++];
206 if (lowByte == 0)
207 {
208 return stringBuilder.ToString();
209 }
210
211 if (lowByte > 0x7f)
212 {
213 highByte = data[offset++];
214 if (highByte == 0)
215 {
216 return stringBuilder.ToString();
217 }
218 stringBuilder.Append(encoding.GetString(new byte[] { lowByte, highByte }));
219 }
220 else
221 {
222 stringBuilder.Append((char)lowByte);
223 }
224 }
225 }
226 }
227 }
2 using System.Collections.Generic;
3 using System.Text;
4 using System.IO;
5 using System.Text.RegularExpressions;
6 using System.Net;
7 using System.Net.Sockets;
8
9 namespace AjaxIP
10 {
11 public class IPLocation
12 {
13 public string IP { get; set; }
14 public string Country { get; set; }
15 public string Local { get; set; }
16 }
17
18 public class QQWryLocator
19 {
20 static Encoding encoding = Encoding.GetEncoding("GB2312");
21
22 private byte[] data;
23 int firstStartIpOffset;
24 int lastStartIpOffset;
25 int ipCount;
26
27 public int Count { get { return ipCount; } }
28
29 public QQWryLocator(string dataPath)
30 {
31 using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
32 {
33 data = new byte[fs.Length];
34 fs.Read(data, 0, data.Length);
35 }
36
37 firstStartIpOffset = (int)data[0] + (((int)data[1]) << 8) + (((int)data[2]) << 16) + (((int)data[3]) << 24);
38 lastStartIpOffset = (int)data[4] + (((int)data[5]) << 8) + (((int)data[6]) << 16) + (((int)data[7]) << 24);
39 ipCount = (lastStartIpOffset - firstStartIpOffset) / 7 + 1;
40
41 if (ipCount <= 1)
42 {
43 throw new ArgumentException("ip FileDataError");
44 }
45 }
46
47 public static uint IpToInt(string ip)
48 {
49 //string[] strArray = ip.Split('.');
50 //return (uint.Parse(strArray[0]) << 24) + (uint.Parse(strArray[1]) << 16) + (uint.Parse(strArray[2]) << 8) + uint.Parse(strArray[0]);
51 //return (uint)IPAddress.HostToNetworkOrder((int)(IPAddress.Parse(ip).Address));
52
53 byte[] bytes = IPAddress.Parse(ip).GetAddressBytes();
54 return (uint)bytes[3] + (((uint)bytes[2]) << 8) + (((uint)bytes[1]) << 16) + (((uint)bytes[0]) << 24);
55 }
56
57 public static string IntToIP(uint ip_Int)
58 {
59 return new IPAddress(ip_Int).ToString();
60 }
61
62 public IPLocation Query(string ip)
63 {
64 IPAddress address = IPAddress.Parse(ip);
65 if (address.AddressFamily != AddressFamily.InterNetwork)
66 {
67 throw new ArgumentException("不支持非IPV4的地址");
68 }
69
70 if (IPAddress.IsLoopback(address))
71 {
72 return new IPLocation() { IP = ip, Country = "本机内部环回地址", Local = string.Empty };
73 }
74
75 uint intIP = (uint)IPAddress.HostToNetworkOrder((int)address.Address);
76
77 //if ((((intIP >= IpToInt("0.0.0.0")) && (intIP <= IpToInt("2.255.255.255"))) || ((intIP >= IpToInt("64.0.0.0")) && (intIP <= IpToInt("126.255.255.255")))) ||
78 //((intIP >= IpToInt("58.0.0.0")) && (intIP <= IpToInt("60.255.255.255"))))
79 //if (intIP <= 50331647 || (intIP >= 1073741824 && intIP <= 2130706431) || (intIP >= 973078528 && intIP <= 1023410175))
80 //{
81 // return new IPLocation() { IP = ip, Country = "网络保留地址", Local = string.Empty };
82 //}
83
84 IPLocation ipLocation = new IPLocation() { IP = ip };
85
86 uint right = (uint)ipCount;
87 uint left = 0;
88 uint middle = 0;
89 uint startIp = 0;
90 uint endIpOff = 0;
91 uint endIp = 0;
92 int countryFlag = 0;
93
94 while (left < (right - 1))
95 {
96 middle = (right + left) / 2;
97 startIp = GetStartIp(middle, out endIpOff);
98 if (intIP == startIp)
99 {
100 left = middle;
101 break;
102 }
103 if (intIP > startIp)
104 {
105 left = middle;
106 }
107 else
108 {
109 right = middle;
110 }
111 }
112 startIp = GetStartIp(left, out endIpOff);
113 endIp = GetEndIp(endIpOff, out countryFlag);
114 if ((startIp <= intIP) && (endIp >= intIP))
115 {
116 string local;
117 ipLocation.Country = GetCountry(endIpOff, countryFlag, out local);
118 ipLocation.Local = local;
119 }
120 else
121 {
122 ipLocation.Country = "未知";
123 ipLocation.Local = string.Empty;
124 }
125 return ipLocation;
126 }
127
128 private uint GetStartIp(uint left, out uint endIpOff)
129 {
130 int leftOffset = (int)(firstStartIpOffset + (left * 7));
131 endIpOff = (uint)data[4 + leftOffset] + (((uint)data[5 + leftOffset]) << 8) + (((uint)data[6 + leftOffset]) << 16);
132 return (uint)data[leftOffset] + (((uint)data[1 + leftOffset]) << 8) + (((uint)data[2 + leftOffset]) << 16) + (((uint)data[3 + leftOffset]) << 24);
133 }
134
135 private uint GetEndIp(uint endIpOff, out int countryFlag)
136 {
137 countryFlag = data[4 + endIpOff];
138 return (uint)data[endIpOff] + (((uint)data[1 + endIpOff]) << 8) + (((uint)data[2 + endIpOff]) << 16) + (((uint)data[3 + endIpOff]) << 24);
139 }
140
141 /// <summary>
142 /// Gets the country.
143 /// </summary>
144 /// <param name="endIpOff">The end ip off.</param>
145 /// <param name="countryFlag">The country flag.</param>
146 /// <param name="local">The local.</param>
147 /// <returns>country</returns>
148 private string GetCountry(uint endIpOff, int countryFlag, out string local)
149 {
150 string country = string.Empty;
151 uint offset = endIpOff + 4;
152 switch (countryFlag)
153 {
154 case 1:
155 case 2:
156 country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
157 offset = endIpOff + 8;
158 local = (1 == countryFlag) ? string.Empty : GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
159 break;
160 default:
161 country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
162 local = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
163 break;
164 }
165 return country;
166 }
167
168 private string GetFlagStr(ref uint offset, ref int countryFlag, ref uint endIpOff)
169 {
170 int flag = 0;
171 while (true)
172 {
173 flag = data[offset];
174 //没有重定向
175 if (flag != 1 && flag != 2)
176 {
177 break;
178 }
179 if (flag == 2)
180 {
181 countryFlag = 2;
182 endIpOff = offset - 4;
183 }
184 offset = (uint)data[1 + offset] + (((uint)data[2 + offset]) << 8) + (((uint)data[3 + offset]) << 16);
185 }
186 if (offset < 12)
187 {
188 return string.Empty;
189 }
190 return GetStr(ref offset);
191 }
192
193 /// <summary>
194 /// 读取字符串...
195 /// </summary>
196 /// <param name="offset"></param>
197 /// <returns></returns>
198 private string GetStr(ref uint offset)
199 {
200 byte lowByte = 0;
201 byte highByte = 0;
202 StringBuilder stringBuilder = new StringBuilder(16);
203 while (true)
204 {
205 lowByte = data[offset++];
206 if (lowByte == 0)
207 {
208 return stringBuilder.ToString();
209 }
210
211 if (lowByte > 0x7f)
212 {
213 highByte = data[offset++];
214 if (highByte == 0)
215 {
216 return stringBuilder.ToString();
217 }
218 stringBuilder.Append(encoding.GetString(new byte[] { lowByte, highByte }));
219 }
220 else
221 {
222 stringBuilder.Append((char)lowByte);
223 }
224 }
225 }
226 }
227 }
再来新建 IPSearch.ashx 文件,如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System;
2 using System.Collections;
3 using System.Data;
4 using System.Linq;
5 using System.Web;
6 using System.Web.Services;
7 using System.Web.Services.Protocols;
8 using System.Xml.Linq;
9
10 namespace AjaxIP
11 {
12 /// <summary>
13 /// IP查询 的摘要说明
14 /// </summary>
15 public class IPSearch : IHttpHandler
16 {
17
18 public void ProcessRequest(HttpContext context)
19 {
20 context.Response.ContentType = "text/plain";
21 string ip = context.Request["ip"];
22 string ipFilePath = @"\App_Data\QQWry.dat";
23 QQWryLocator QQWry = new QQWryLocator(ipFilePath);
24 IPLocation loc = QQWry.Query(ip);
25
26 context.Response.Write(string.Format("{0} {1}",loc.Country,loc.Local));
27 }
28
29 public bool IsReusable
30 {
31 get
32 {
33 return false;
34 }
35 }
36 }
37 }
2 using System.Collections;
3 using System.Data;
4 using System.Linq;
5 using System.Web;
6 using System.Web.Services;
7 using System.Web.Services.Protocols;
8 using System.Xml.Linq;
9
10 namespace AjaxIP
11 {
12 /// <summary>
13 /// IP查询 的摘要说明
14 /// </summary>
15 public class IPSearch : IHttpHandler
16 {
17
18 public void ProcessRequest(HttpContext context)
19 {
20 context.Response.ContentType = "text/plain";
21 string ip = context.Request["ip"];
22 string ipFilePath = @"\App_Data\QQWry.dat";
23 QQWryLocator QQWry = new QQWryLocator(ipFilePath);
24 IPLocation loc = QQWry.Query(ip);
25
26 context.Response.Write(string.Format("{0} {1}",loc.Country,loc.Local));
27 }
28
29 public bool IsReusable
30 {
31 get
32 {
33 return false;
34 }
35 }
36 }
37 }
最后在Default.aspx页面写下,js和有IP的用户信息,如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
3 <html xmlns="http://www.w3.org/1999/xhtml" >
4 <head runat="server">
5 <title></title>
6 <script language="javascript" src="Js/jquery-1.3.1.js"></script>
7 <script language="javascript">
8 $(document).ready(function() {
9 $("#tb tr").each(function() {
10 var obj = $(this).children("td:eq(2)");
11 SearchIP(obj);
12 });
13 })
14
15 function SearchIP(obj) {
16 $.ajax({
17 type: "GET",
18 url: "IPSearch.ashx?ip=" + obj.text(),
19 success: function(data) {
20 obj.text(data);
21 }
22 });
23 }
24 </script>
25 </head>
26 <body>
27 <form id="form1" runat="server">
28 <div>
29
30 <table id="tb" style="width:100%;">
31 <thead>
32 <th>321321</th>
33 <th>321321</th>
34 <th>321321</th>
35 </thead>
36 <tr>
37 <td>
38 OMEGA</td>
39 <td>
40 0</td>
41 <td>
42 122.229.191.8</td>
43 </tr>
44 <tr>
45 <td>
46 荒年</td>
47 <td>
48 900,000</td>
49 <td>
50 110.87.98.30</td>
51 </tr>
52 <tr>
53 <td>
54 寒妃</td>
55 <td>
56 1,854,257,979</td>
57 <td>
58 220.188.193.72</td>
59 </tr>
60 <tr>
61 <td>
62 哈小土</td>
63 <td>
64 600,100</td>
65 <td>
66 220.188.193.72</td>
67 </tr>
68 <tr>
69 <td>
70 化妆造型</td>
71 <td>
72 400,100</td>
73 <td>
74 220.188.193.72</td>
75 </tr>
76 </table>
77
78 </div>
79 </form>
80 </body>
81 </html>
2
3 <html xmlns="http://www.w3.org/1999/xhtml" >
4 <head runat="server">
5 <title></title>
6 <script language="javascript" src="Js/jquery-1.3.1.js"></script>
7 <script language="javascript">
8 $(document).ready(function() {
9 $("#tb tr").each(function() {
10 var obj = $(this).children("td:eq(2)");
11 SearchIP(obj);
12 });
13 })
14
15 function SearchIP(obj) {
16 $.ajax({
17 type: "GET",
18 url: "IPSearch.ashx?ip=" + obj.text(),
19 success: function(data) {
20 obj.text(data);
21 }
22 });
23 }
24 </script>
25 </head>
26 <body>
27 <form id="form1" runat="server">
28 <div>
29
30 <table id="tb" style="width:100%;">
31 <thead>
32 <th>321321</th>
33 <th>321321</th>
34 <th>321321</th>
35 </thead>
36 <tr>
37 <td>
38 OMEGA</td>
39 <td>
40 0</td>
41 <td>
42 122.229.191.8</td>
43 </tr>
44 <tr>
45 <td>
46 荒年</td>
47 <td>
48 900,000</td>
49 <td>
50 110.87.98.30</td>
51 </tr>
52 <tr>
53 <td>
54 寒妃</td>
55 <td>
56 1,854,257,979</td>
57 <td>
58 220.188.193.72</td>
59 </tr>
60 <tr>
61 <td>
62 哈小土</td>
63 <td>
64 600,100</td>
65 <td>
66 220.188.193.72</td>
67 </tr>
68 <tr>
69 <td>
70 化妆造型</td>
71 <td>
72 400,100</td>
73 <td>
74 220.188.193.72</td>
75 </tr>
76 </table>
77
78 </div>
79 </form>
80 </body>
81 </html>
这样我们的后台用户信息不再是不友好的IP地址段了。
运行一下,看看效果吧。
作者:Kurodo
出处:http://Kurodo.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://Kurodo.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。