当前位置:   article > 正文

springboot项目获取真实用户ip(不是虚拟ip)_springboot 获取真实ip

springboot 获取真实ip

最近在工作中遇见一个业务场景是获取用户真实的ip地址。就跟现在网上评论展示ip一样的业务场景。然后自己就去了解了一下,

1、pom依赖配置

  1. <!--查询ip归属地-->
  2. <dependency>
  3. <groupId>org.lionsoul</groupId>
  4. <artifactId>ip2region</artifactId>
  5. <version>1.7.2</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>commons-io</groupId>
  9. <artifactId>commons-io</artifactId>
  10. <version>2.5</version>
  11. </dependency>

2、 ip2region.db文件

工具类里面需要使用ip2region.db这个文件。在加载的时候,需要下载仓库中的 ip2region.db 文件,然后放到 resource 目录下

以下文件是文件链接,可自取。


链接:https://pan.baidu.com/s/1PDd_BnpdaOOkYnAc5cB36A?pwd=LA7M 
 

3、工具类

本工具类会将完整的封装方法放入,在使用的时候只需要自己调用即可,非常简单明了。

在工具类里面也会将具体的方法导的具体的包显示出来,便于自己查看溯源。

  1. import lombok.extern.slf4j.Slf4j;
  2. import org.apache.commons.io.FileUtils;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.lionsoul.ip2region.DataBlock;
  5. import org.lionsoul.ip2region.DbConfig;
  6. import org.lionsoul.ip2region.DbSearcher;
  7. import org.lionsoul.ip2region.Util;
  8. import org.springframework.core.io.Resource;
  9. import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
  10. import org.springframework.core.io.support.ResourcePatternResolver;
  11. import javax.servlet.http.HttpServletRequest;
  12. import java.io.File;
  13. import java.io.InputStream;
  14. import java.lang.reflect.Method;
  15. @Slf4j
  16. public class IpUtil {
  17. public static String getIpAddr(HttpServletRequest request) {
  18. String ip = request.getHeader("X-Real-IP");
  19. if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
  20. return ip;
  21. }
  22. ip = request.getHeader("X-Forwarded-For");
  23. if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
  24. // 多次反向代理后会有多个IP值,第一个为真实IP。
  25. int index = ip.indexOf(',');
  26. if (index != -1) {
  27. return ip.substring(0, index);
  28. } else {
  29. return ip;
  30. }
  31. } else {
  32. return request.getRemoteAddr();
  33. }
  34. }
  35. public static String getCityInfo(String ip) throws Exception {
  36. //获得文件流时,因为读取的文件是在打好jar文件里面,不能直接通过文件资源路径拿到文件,但是可以在jar包中拿到文件流
  37. ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
  38. Resource[] resources = resolver.getResources("ip2region.db");
  39. Resource resource = resources[0];
  40. InputStream is = resource.getInputStream();
  41. File target = new File("ip2region.db");
  42. FileUtils.copyInputStreamToFile(is, target);
  43. is.close();
  44. if (StringUtils.isEmpty(String.valueOf(target))) {
  45. log.error("Error: Invalid ip2region.db file");
  46. return null;
  47. }
  48. DbConfig config = new DbConfig();
  49. DbSearcher searcher = new DbSearcher(config, String.valueOf(target));
  50. //查询算法
  51. //B-tree, B树搜索(更快)
  52. int algorithm = DbSearcher.BTREE_ALGORITHM;
  53. try {
  54. //define the method
  55. Method method;
  56. method = searcher.getClass().getMethod("btreeSearch", String.class);
  57. DataBlock dataBlock;
  58. if (!Util.isIpAddress(ip)) {
  59. log.error("Error: Invalid ip address");
  60. }
  61. dataBlock = (DataBlock) method.invoke(searcher, ip);
  62. String ipInfo = dataBlock.getRegion();
  63. if (!StringUtils.isEmpty(ipInfo)) {
  64. ipInfo = ipInfo.replace("|0", "");
  65. ipInfo = ipInfo.replace("0|", "");
  66. }
  67. return ipInfo;
  68. } catch (Exception e) {
  69. e.printStackTrace();
  70. }
  71. return null;
  72. }
  73. public static String getIpPossession(String ip) throws Exception {
  74. String cityInfo = getCityInfo(ip);
  75. if (!StringUtils.isEmpty(cityInfo)) {
  76. cityInfo = cityInfo.replace("|", " ");
  77. String[] cityList = cityInfo.split(" ");
  78. if (cityList.length > 0) {
  79. // 国内的显示到具体的省
  80. if ("中国".equals(cityList[0])) {
  81. if (cityList.length > 1) {
  82. return cityList[1];
  83. }
  84. }
  85. // 国外显示到国家
  86. return cityList[0];
  87. }
  88. }
  89. return "未知";
  90. }
  91. }

4、方法调用

此时就可以显示正常信息了。

5、问题总结 

 如果显示这个错误的话,说明本地自己写的AOP,joinPoint.getArgs()返回的数组中携带有Request或者Response对象,导致序列化异常。

这个时候我们添加如下就可以4了

  1. Object[] args = point.getArgs();
  2. Object[] arguments = new Object[args.length];
  3. for (int i = 0; i < args.length; i++) {
  4. if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
  5. //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
  6. //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
  7. continue;
  8. }
  9. arguments[i] = args[i];
  10. }
  11. String paramter = "";
  12. if (arguments != null) {
  13. try {
  14. paramter = JSONObject.toJSONString(arguments);
  15. } catch (Exception e) {
  16. paramter = arguments.toString();
  17. }
  18. }
  19. log.info("请求接口名:{}", point.getSignature().getName());
  20. log.info("请求参数:{}", paramter);
  21. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/405757
推荐阅读
相关标签
  

闽ICP备14008679号