一、获取IP
获取IP有两种方式:1、自定义ip工具类。2、security获取。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import javax.servlet.http.HttpServletRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
public class IPUtils {
private static final String UNKNOWN = "unknown";
protected IPUtils() {
}
/**
* 获取IP地址 使用 Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非
* unknown的有效IP字符串,则为真实IP地址
*/
public static String getClientIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个ip值,第一个ip才是真实ip
if (ip.indexOf(",") != -1) {
ip = ip.split(",")[0];
}
}
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("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
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();
}
// log.info("获取客户端ip: " + ip);
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
/**
* 判断是否为内网
* @param ipAddress
* @return
*/
public static boolean isInnerIP(String ipAddress) {
boolean isInnerIp = false;
if (ipAddress.indexOf(",") != -1) {
ipAddress = ipAddress.split(",")[0];
}
ipAddress = ipAddress.replaceAll(",", ".").replaceAll(" ", "");
long ipNum = getIpNum(ipAddress);
/**
* 私有IP:
* A类 10.0.0.0-10.255.255.255
* B类 172.16.0.0-172.31.255.255
* C类 192.168.0.0-192.168.255.255
当然,还有127这个网段是环回地址
**/
long aBegin = getIpNum("10.0.0.0");
long aEnd = getIpNum("10.255.255.255");
long bBegin = getIpNum("172.16.0.0");
long bEnd = getIpNum("172.31.255.255");
long cBegin = getIpNum("192.168.0.0");
long cEnd = getIpNum("192.168.255.255");
isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd)
|| ipAddress.equals("127.0.0.1");
return isInnerIp;
}
private static long getIpNum(String ipAddress) {
String[] ip = ipAddress.split("\\.");
long a = Integer.parseInt(ip[0]);
long b = Integer.parseInt(ip[1]);
long c = Integer.parseInt(ip[2]);
long d = Integer.parseInt(ip[3]);
long ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
return ipNum;
}
private static boolean isInner(long userIp, long begin, long end) {
return (userIp >= begin) && (userIp <= end);
}
/**
* 此方法调用百度AIP来查询IP所在地域(YYR)
* @param strIP(传入的IP地址)
* @return
*/
public static String getAddressByIP(String strIP) {
try {
URL url = new URL("http://api.map.baidu.com/location/ip?ak=F454f8a5efe5e577997931cc01de3974&ip="+strIP);
URLConnection conn = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line = null;
StringBuffer result = new StringBuffer();
while ((line = reader.readLine()) != null) {
result.append(line);
}
reader.close();
String ipAddr = result.toString();
try {
JSONObject obj1= JSON.parseObject(ipAddr);
if("0".equals(obj1.get("status").toString())){
JSONObject obj2= JSON.parseObject(obj1.get("content").toString());
JSONObject obj3= JSON.parseObject(obj2.get("address_detail").toString());
return obj3.get("province").toString()+obj3.get("city").toString();
}else{
return "读取失败";
}
} catch (JSONException e) {
e.printStackTrace();
return "读取失败";
}
} catch (IOException e) {
return "读取失败";
}
}
public static String getAddress(String ip) {
String loginAddress = null;
try {
if (ip.indexOf(",") != -1) {
ip = ip.split(",")[0];
}
if("127.0.0.1".equals(ip) || isInnerIP(ip)) {
loginAddress = "局域网";
}else{
loginAddress = getAddressByIP(ip);
if("读取失败".equals(loginAddress)) {
loginAddress = null;
}
}
return loginAddress;
} catch (Exception e) {
return null;
}
}
}
在自定义的登录部分MyAuthenticationProvider 直接使用以下代码即可。
WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails();
String userIp = details.getRemoteAddress();
二、过滤IP
可以直接在Security的配置类中直接限制,指定ip时使用X.X.X.X ,若是ip段可是采用X.X.X.X/Y
//多个
http.authorizeRequests()
.antMatchers("/api/**", "/info")
.access("hasIpAddress('X.X.X.X') or hasIpAddress('Y.Y.Y.Y')")
//单个
http.authorizeRequests()
.antMatchers("/api/**", "/info").hasIpAddress("127.0.0.0/16")
自定义校验时,对访问ip的限制可以配置ip段,
public static boolean isInRange(String ip, String cidr) {
String[] ips = ip.split("\\.");
int ipAddr = (Integer.parseInt(ips[0]) << 24) | (Integer.parseInt(ips[1]) << 16) | (Integer.parseInt(ips[2]) << 8) | Integer.parseInt(ips[3]);
int type = Integer.parseInt(cidr.replaceAll(".*/", ""));
int mask = 0xFFFFFFFF << (32 - type);
String cidrIp = cidr.replaceAll("/.*", "");
String[] cidrIps = cidrIp.split("\\.");
int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24) | (Integer.parseInt(cidrIps[1]) << 16) | (Integer.parseInt(cidrIps[2]) << 8) | Integer.parseInt(cidrIps[3]);
return (ipAddr & mask) == (cidrIpAddr & mask);
}
在数据库或其他地方保存指定的多个ip,使用lamda或者for处理。
List<String> list = new ArrayList<String>();
list.add("127.0.0.1");
list.add("127.0.0.2");
list.add("127.0.0.4");
String ip = "127.0.0.6";
boolean bString = list.stream().anyMatch(p -> p.equals(ip));
也可以针对用指定固定ip,查询用户数据直接比较即可。