刘仁 Java后端开发

SpringBoot中跟IP获取登录用户的位置信息的第三方接口

2020-05-21
LIUREN
IP

SpringBoot中跟IP获取登录用户的位置信息的第三方接口

大部分场景下,我们都会在项目中记录登录用户或者操作用户的IP地址信息和根据IP解析出的地理位置信息。目前市场上开放的API接口,目前免费的并且我能知道的就淘宝的还有一个公共网络的两个。目前淘宝的会做qps限流,导致频繁登录会出现获取不到地理位置信息。然后就换成了另外一个,在这里作为记录跟IP获取地理位置信息的工具代码,方便以后可以单独提取出来直接使用。

协议:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/

版权声明:本文为原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

1. 获取IP方法的工具类

package com.kelan.common.utils;

import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;

/**
 * 获取IP方法
 * 
 * @author ruoyi
 */
public class IpUtils
{
    public static String getIpAddr(HttpServletRequest request)
    {
        if (request == null)
        {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Real-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }

        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

    public static boolean internalIp(String ip)
    {
        byte[] addr = textToNumericFormatV4(ip);
        return internalIp(addr) || "127.0.0.1".equals(ip);
    }

    private static boolean internalIp(byte[] addr)
    {
        if (StringUtils.isNull(addr) || addr.length < 2)
        {
            return true;
        }
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0)
        {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4)
                {
                    return true;
                }
            case SECTION_5:
                switch (b1)
                {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }

    /**
     * 将IPv4地址转换成字节
     * 
     * @param text IPv4地址
     * @return byte 字节
     */
    public static byte[] textToNumericFormatV4(String text)
    {
        if (text.length() == 0)
        {
            return null;
        }

        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try
        {
            long l;
            int i;
            switch (elements.length)
            {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                        return null;
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                        return null;
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                        return null;
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                        return null;
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        }
        catch (NumberFormatException e)
        {
            return null;
        }
        return bytes;
    }

    public static String getHostIp()
    {
        try
        {
            return InetAddress.getLocalHost().getHostAddress();
        }
        catch (UnknownHostException e)
        {
        }
        return "127.0.0.1";
    }

    public static String getHostName()
    {
        try
        {
            return InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException e)
        {
        }
        return "未知";
    }
}

2. 获取IP地址地理位置信息工具类

package com.kelan.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.kelan.common.config.Global;
import com.kelan.common.json.JSON;
import com.kelan.common.json.JSONObject;
import com.kelan.common.utils.http.HttpUtils;

/**
 * 获取地址类
 * 
 * @author kelan
 */
public class AddressUtils
{
    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);

    public static final String IP_URL = "http://gwgp-hye6ycojwut.n.bdcloudapi.com/getIpInfo";

    public static String getRealAddressByIP(String ip)
    {
        String address = "XX XX";

        // 内网不查询
        if (IpUtils.internalIp(ip))
        {
            return "内网IP";
        }
        if (Global.isAddressEnabled())
        {
            String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip);
            if (StringUtils.isEmpty(rspStr))
            {
                log.error("获取地理位置异常 {}", ip);
                return address;
            }
            JSONObject obj;
            try
            {
                obj = JSON.unmarshal(rspStr, JSONObject.class);
                JSONObject data = obj.getObj("data");
                String country = data.getStr("country");
                String prov = data.getStr("prov");
                String city = data.getStr("city");
                String isp = data.getStr("isp");
                address = country + " " + prov + " " + city + " " + isp;
            }
            catch (Exception e)
            {
                log.error("获取地理位置异常 {}", ip);
            }
        }
        return address;
    }
}

3. 第三方IP地理位置信息获取的接口地址:

gwgp:http://gwgp-hye6ycojwut.n.bdcloudapi.com/getIpInfo?ip=123.116.182.163

taobao:http://ip.taobao.com/service/getIpInfo.php?ip=123.116.182.163

请求工具类

   package com.kelan.common.utils.http;
   
   import java.io.BufferedReader;
   import java.io.IOException;
   import java.io.InputStream;
   import java.io.InputStreamReader;
   import java.io.PrintWriter;
   import java.net.ConnectException;
   import java.net.SocketTimeoutException;
   import java.net.URL;
   import java.net.URLConnection;
   import java.security.cert.X509Certificate;
   import javax.net.ssl.HostnameVerifier;
   import javax.net.ssl.HttpsURLConnection;
   import javax.net.ssl.SSLContext;
   import javax.net.ssl.SSLSession;
   import javax.net.ssl.TrustManager;
   import javax.net.ssl.X509TrustManager;
   import org.slf4j.Logger;
   import org.slf4j.LoggerFactory;
   
   /**
    * 通用http发送方法
    * 
    * @author ruoyi
    */
   public class HttpUtils
   {
       private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
   
       /**
        * 向指定 URL 发送GET方法的请求
        *
        * @param url 发送请求的 URL
        * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
        * @return 所代表远程资源的响应结果
        */
       public static String sendGet(String url, String param)
       {
           StringBuilder result = new StringBuilder();
           BufferedReader in = null;
           try
           {
               String urlNameString = url + "?" + param;
               log.info("sendGet - {}", urlNameString);
               URL realUrl = new URL(urlNameString);
               URLConnection connection = realUrl.openConnection();
               connection.setRequestProperty("accept", "*/*");
               connection.setRequestProperty("connection", "Keep-Alive");
               connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
               connection.connect();
               in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
               String line;
               while ((line = in.readLine()) != null)
               {
                   result.append(line);
               }
               log.info("recv - {}", result);
           }
           catch (ConnectException e)
           {
               log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
           }
           catch (SocketTimeoutException e)
           {
               log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
           }
           catch (IOException e)
           {
               log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
           }
           catch (Exception e)
           {
               log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
           }
           finally
           {
               try
               {
                   if (in != null)
                   {
                       in.close();
                   }
               }
               catch (Exception ex)
               {
                   log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
               }
           }
           return result.toString();
       }
   
       /**
        * 向指定 URL 发送POST方法的请求
        *
        * @param url 发送请求的 URL
        * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
        * @return 所代表远程资源的响应结果
        */
       public static String sendPost(String url, String param)
       {
           PrintWriter out = null;
           BufferedReader in = null;
           StringBuilder result = new StringBuilder();
           try
           {
               String urlNameString = url + "?" + param;
               log.info("sendPost - {}", urlNameString);
               URL realUrl = new URL(urlNameString);
               URLConnection conn = realUrl.openConnection();
               conn.setRequestProperty("accept", "*/*");
               conn.setRequestProperty("connection", "Keep-Alive");
               conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
               conn.setRequestProperty("Accept-Charset", "utf-8");
               conn.setRequestProperty("contentType", "utf-8");
               conn.setDoOutput(true);
               conn.setDoInput(true);
               out = new PrintWriter(conn.getOutputStream());
               out.print(param);
               out.flush();
               in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
               String line;
               while ((line = in.readLine()) != null)
               {
                   result.append(line);
               }
               log.info("recv - {}", result);
           }
           catch (ConnectException e)
           {
               log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
           }
           catch (SocketTimeoutException e)
           {
               log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
           }
           catch (IOException e)
           {
               log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
           }
           catch (Exception e)
           {
               log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
           }
           finally
           {
               try
               {
                   if (out != null)
                   {
                       out.close();
                   }
                   if (in != null)
                   {
                       in.close();
                   }
               }
               catch (IOException ex)
               {
                   log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
               }
           }
           return result.toString();
       }
   
       public static String sendSSLPost(String url, String param)
       {
           StringBuilder result = new StringBuilder();
           String urlNameString = url + "?" + param;
           try
           {
               log.info("sendSSLPost - {}", urlNameString);
               SSLContext sc = SSLContext.getInstance("SSL");
               sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
               URL console = new URL(urlNameString);
               HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
               conn.setRequestProperty("accept", "*/*");
               conn.setRequestProperty("connection", "Keep-Alive");
               conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
               conn.setRequestProperty("Accept-Charset", "utf-8");
               conn.setRequestProperty("contentType", "utf-8");
               conn.setDoOutput(true);
               conn.setDoInput(true);
   
               conn.setSSLSocketFactory(sc.getSocketFactory());
               conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
               conn.connect();
               InputStream is = conn.getInputStream();
               BufferedReader br = new BufferedReader(new InputStreamReader(is));
               String ret = "";
               while ((ret = br.readLine()) != null)
               {
                   if (ret != null && !ret.trim().equals(""))
                   {
                       result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8"));
                   }
               }
               log.info("recv - {}", result);
               conn.disconnect();
               br.close();
           }
           catch (ConnectException e)
           {
               log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
           }
           catch (SocketTimeoutException e)
           {
               log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
           }
           catch (IOException e)
           {
               log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
           }
           catch (Exception e)
           {
               log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
           }
           return result.toString();
       }
   
       private static class TrustAnyTrustManager implements X509TrustManager
       {
           @Override
           public void checkClientTrusted(X509Certificate[] chain, String authType)
           {
           }
   
           @Override
           public void checkServerTrusted(X509Certificate[] chain, String authType)
           {
           }
   
           @Override
           public X509Certificate[] getAcceptedIssuers()
           {
               return new X509Certificate[] {};
           }
       }
   
       private static class TrustAnyHostnameVerifier implements HostnameVerifier
       {
           @Override
           public boolean verify(String hostname, SSLSession session)
           {
               return true;
           }
       }
   }

博客地址:https://www.codepeople.cn

=====================================================================

微信公众号:


Similar Posts

Comments