• 后台增加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的组件类,如下:

    代码
      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 { getset; }
     14         public string Country { getset; }
     15         public string Local { getset; }
     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 文件,如下:

    代码
     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 }

    最后在Default.aspx页面写下,js和有IP的用户信息,如下:

    代码
     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="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地址段了。

    运行一下,看看效果吧。

  • 相关阅读:
    如何使用Remoting实现双工(转自Artech)
    解决自定义代码启动Approver Sharepoint 2010 Workflow,出现Failed on Start
    设计模式学习(目录)
    C#面向对象分析
    使用Sharepoint 2010 Client Object Model 通过SSL验证
    .NET 4.0 Location : 查看传感器状态变化
    OLAP和OLTP的 概念和区别
    组织结构及权限模型设计
    维度关系
    PHP正则替换中文让中文无处可躲
  • 原文地址:https://www.cnblogs.com/Kurodo/p/1848270.html
Copyright © 2020-2023  润新知