分析总结
服务器端获取访问者外网iP的核心代码就是下面这一行代码,需要特别注意的是下面这行代码只能在服务器端使用才能获取外网地址,在本地开发环境获取到的是内网IP,亲测有效,至于我提供的工具类只是更加全面的情况而已。另外想要通过下面代码获取的话需要代理服务器做一些相关配置,ng的配置方式可以参考这个:主机配置nginx后如何获取访问者IP
request.getRemoteAddr();
客户端获取外网IP地址的方式核心代码如下(完整代码到下面获取),通过模拟HTTP请求访问http://www.icanhazip.com接口接收返回的访问者IP地址数据。此方法只能在开发环境下有效,因为运行代码端是自己的电脑,开发环境下运营代码的电脑和访问者肯定是同一个网段,所以如果这个方法发布在服务器上后就一直获取到的是服务器外网IP地址,所以下面的方法只适合用来玩一玩
String ipAddr = IpUtil.getIpAddr(request);//获取ip地址
boolean internalIp = internalIp(ipAddr);//判断ip是否内网ip
log.info("ipAddr={}", ipAddr);
log.info("internalIp={}", internalIp);
if (!internalIp) {//外网地址直接返回
log.info("直接返回外网IP={}", ipAddr);
return ipAddr;
}
String result = "";
URLConnection connection;
BufferedReader in = null;
try {
URL url = new URL("http://www.icanhazip.com");
connection = url.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "KeepAlive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.setConnectTimeout(3000);
connection.setReadTimeout(3000);
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
log.info("URLConnection建立连接返回result={}", result);
return result;
完整代码
AddressUtils
import lombok.extern.slf4j.Slf4j;
import sun.net.util.IPAddressUtil;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* * ip地址工具类
* * @author ACGkaka
* *
*/
@Slf4j
public class AddressUtils {
/**
* @param
* @throws Exception
* @todo 获取外网ip
* @date 2018年11月12日
* @author yanan
*/
public static String getOuterNetIp(HttpServletRequest request) throws Exception {
String ipAddr = IpUtil.getIpAddr(request);//获取ip地址
boolean internalIp = internalIp(ipAddr);//判断ip是否内网ip
log.info("ipAddr={}", ipAddr);
log.info("internalIp={}", internalIp);
if (!internalIp) {//外网地址直接返回
log.info("直接返回外网IP={}", ipAddr);
return ipAddr;
}
String result = "";
URLConnection connection;
BufferedReader in = null;
try {
URL url = new URL("http://www.icanhazip.com");
connection = url.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "KeepAlive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.setConnectTimeout(3000);
connection.setReadTimeout(3000);
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
log.info("URLConnection建立连接返回result={}", result);
return result;
}
/**
* @param
* @todo 判断是否内网ip
* @date 2018年11月12日
* @author yanan
*/
public static boolean internalIp(String ip) {
if ("127.0.0.1".equalsIgnoreCase(ip))
return true;
if ("0:0:0:0:0:0:0:1".equals(ip))
return true;
byte[] addr = IPAddressUtil.textToNumericFormatV4(ip);
return internalIp(addr);
}
/**
* @param
* @todo 判断解析后的ip是否内网
* @date 2018年11月12日
* @author yanan
*/
public static boolean internalIp(byte[] addr) {
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;
// 127.0.0.1/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;
}
}
}
HttpUtil
package com.luntek.certificate.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* @author Czw
* @Description HTTP相关工具类
* @Date 2019/4/11 0011 上午 10:46
*/
@Slf4j
@Service
public class HttpUtil {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
return builder.build();
}
/**
* 通过response发送Excel表格
*
* @author Czw
* @date 2019/4/11 0011 下午 12:56
*/
public static HttpServletResponse setExcelResponse(HttpServletResponse response, String className) throws UnsupportedEncodingException {
//防止文件名乱码
String name = new String(className.getBytes(), "ISO8859-1");
response.reset(); // 清除buffer缓存
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + name + ".xlsx");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
return response;
}
@Autowired
private RestTemplate restTemplate;
// Get请求
public String Get(String url, Map<String, Object> params) {
String uri = buildUri(url, params);
ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);
return response.getBody();
}
// Post请求(JSON请求头)
public String JPost(String url, Map<String, Object> params) {
HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, jsonHeaderBuilder());
log.info("****req:{}****", request);
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
return response.getBody();
}
// Post请求(URL请求头)
public String UPost(String url, MultiValueMap<String, String> params) {
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, urlHeaderBuilder());
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
return response.getBody();
}
// 拼接Url和参数
private String buildUri(String url, Map<String, Object> params) {
StringBuilder sb = new StringBuilder(url);
sb.append("?");
for (Map.Entry<String, Object> entry : params.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
// 构建Url请求头
private HttpHeaders urlHeaderBuilder() {
HttpHeaders h = new HttpHeaders();
h.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
return h;
}
// 构建Json请求头
private HttpHeaders jsonHeaderBuilder() {
HttpHeaders h = new HttpHeaders();
h.setContentType(MediaType.APPLICATION_JSON);
return h;
}
}
接口代码
/**
* 测试外网ip获取地址
*
* @return
*/
@ResponseBody
@GetMapping("/testGetAdd")
public ResponseResult testGetAdd(HttpServletRequest request) {
log.info("**********************");
log.info(request.getRemoteAddr());
String ip = null;
try {
ip = AddressUtils.getOuterNetIp(request);
String url="http://ip-api.com/json/"+ip+"?";
Map<String,Object> parm=new HashMap<>();
parm.put("lang=","zh-CN");
String str=httpUtil.Get(url,parm);
JSONObject json = JSONObject.fromObject(str);
return ResponseResult.success(json);
} catch (Exception e) {
e.printStackTrace();
}
return ResponseResult.success(ip);
}
测试效果
网上获取外网ip的方式千篇一律而且很多都不行,找的时候看到下载里面很多都要积分下载的我这就没有设置了,希望大家点个赞就好了,好运~_~