mirror of
https://gitee.com/dromara/MaxKey.git
synced 2025-12-06 17:08:29 +08:00
ip2location support ip2region & GeoLite2
This commit is contained in:
parent
9bff327458
commit
2dda707584
@ -0,0 +1,12 @@
|
||||
|
||||
description = "maxkey-authentication-core"
|
||||
|
||||
|
||||
dependencies {
|
||||
//local jars
|
||||
implementation fileTree(dir: '../maxkey-lib/', include: '*/*.jar')
|
||||
|
||||
implementation project(":maxkey-common")
|
||||
implementation project(":maxkey-core")
|
||||
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.dromara.maxkey.autoconfigure;
|
||||
|
||||
import org.dromara.maxkey.ip2location.IpLocation;
|
||||
import org.dromara.maxkey.ip2location.IpLocationParser;
|
||||
import org.dromara.maxkey.ip2location.offline.GeoIP2V4;
|
||||
import org.dromara.maxkey.ip2location.offline.Ip2regionV2;
|
||||
import org.dromara.maxkey.ip2location.online.Ip138;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
|
||||
@AutoConfiguration
|
||||
public class IpLocationAutoConfiguration implements InitializingBean {
|
||||
static final Logger _logger = LoggerFactory.getLogger(IpLocationAutoConfiguration.class);
|
||||
|
||||
/**
|
||||
* 加载Ip2Region离线库数据 version 2.7.0
|
||||
* @return Ip2regionV2
|
||||
* @throws Exception
|
||||
*/
|
||||
public Ip2regionV2 ip2regionV2() throws Exception {
|
||||
_logger.debug("IpRegion OffLine init...");
|
||||
ClassPathResource resource = new ClassPathResource("/ip2region/ip2region.xdb");
|
||||
byte[] dbBinStr = StreamUtils.copyToByteArray(resource.getInputStream());
|
||||
_logger.debug("ip2region length {}",dbBinStr.length);
|
||||
Searcher searcher = Searcher.newWithBuffer(dbBinStr);
|
||||
return new Ip2regionV2(searcher);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加载GeoIP2离线库数据 version 4.0.1
|
||||
* @return GeoIp2V4
|
||||
* @throws Exception
|
||||
*/
|
||||
public GeoIP2V4 geoIP2() throws Exception {
|
||||
_logger.debug("GeoIP2 OffLine init...");
|
||||
ClassPathResource resource = new ClassPathResource("/geoip2/GeoLite2-City.mmdb");
|
||||
DatabaseReader databaseReader = new DatabaseReader.Builder(resource.getInputStream()).build();
|
||||
return new GeoIP2V4(databaseReader);
|
||||
}
|
||||
|
||||
/**
|
||||
* builder offline provider IpLocation
|
||||
* @param offlineProvider
|
||||
* @return IpLocation
|
||||
*/
|
||||
public IpLocation builderOfflineProvider(String offlineProvider) {
|
||||
IpLocation ipLocationOffLine = null;
|
||||
try {
|
||||
if(offlineProvider.equalsIgnoreCase("none")) {
|
||||
//do nothing
|
||||
_logger.debug("IpLocation offline Provider none");
|
||||
}else if(offlineProvider.equalsIgnoreCase("Ip2Region")){
|
||||
ipLocationOffLine = ip2regionV2();
|
||||
_logger.debug("IpLocation offline Provider Ip2Region");
|
||||
}else if(offlineProvider.equalsIgnoreCase("GeoIp2")){
|
||||
ipLocationOffLine = geoIP2();
|
||||
_logger.debug("IpLocation offline Provider GeoIp2");
|
||||
}
|
||||
}catch(Exception e) {
|
||||
_logger.error("builder Offline IpLocation error", e);
|
||||
}
|
||||
return ipLocationOffLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* builder Online Provider IpLocation
|
||||
* @param onlineProvider
|
||||
* @return IpLocation
|
||||
*/
|
||||
public IpLocation builderOnlineProvider(String onlineProvider) {
|
||||
//need on line provider
|
||||
IpLocation ipLocationOnLine = null;
|
||||
if(onlineProvider.equalsIgnoreCase("none")) {
|
||||
//do nothing
|
||||
_logger.debug("IpLocation online Provider none");
|
||||
}else if(onlineProvider.equalsIgnoreCase("Ip138")){
|
||||
ipLocationOnLine = new Ip138();
|
||||
_logger.debug("IpLocation online Provider Ip138");
|
||||
}
|
||||
return ipLocationOnLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* IP转换区域地址解析
|
||||
* @param isIplocation 是否转换
|
||||
* @param onlineProvider 在线转换实现提供商none/Ip138/Ipchaxun
|
||||
* @param offlineProvider 离线转换实现提供商none/Ip2Region/GeoIp2
|
||||
* @return IpLocationParser
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public IpLocationParser ipLocationParser(
|
||||
@Value("${maxkey.login.iplocation:false}") boolean isIplocation,
|
||||
@Value("${maxkey.login.iplocation.online.provider:none}") String onlineProvider,
|
||||
@Value("${maxkey.login.iplocation.offline.provider:none}") String offlineProvider) throws Exception {
|
||||
return new IpLocationParser(
|
||||
isIplocation,
|
||||
builderOnlineProvider(onlineProvider),
|
||||
builderOfflineProvider(offlineProvider)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package org.dromara.maxkey.ip2location;
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* IpRegion转换抽象类,获取地址Location
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractIpLocation implements IpLocation{
|
||||
|
||||
int failCount = 0;
|
||||
|
||||
public int getFailCount() {
|
||||
return failCount;
|
||||
};
|
||||
|
||||
public int plusFailCount() {
|
||||
return failCount++;
|
||||
};
|
||||
|
||||
|
||||
public String getLocation(String region) {
|
||||
if(region.endsWith("电信") || region.endsWith("移动") || region.endsWith("联通")) {
|
||||
region.substring(0, region.length() - 2).trim();
|
||||
}
|
||||
|
||||
if(region.indexOf(" ") > 0) {
|
||||
return region.split(" ")[0];
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package org.dromara.maxkey.ip2location;
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* IpRegion转换接口
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
public interface IpLocation {
|
||||
public static final String USERAGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36";
|
||||
|
||||
public static final int TIMEOUT = 5000;
|
||||
|
||||
public Region region(String ipAddress);
|
||||
|
||||
public String getLocation(String region);
|
||||
|
||||
public int getFailCount();
|
||||
|
||||
public int plusFailCount() ;
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package org.dromara.maxkey.ip2location;
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 本地(127.0.0.1/0:0:0:0:0:0:0:1)地址
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
public class IpLocationLocal extends AbstractIpLocation implements IpLocation{
|
||||
|
||||
@Override
|
||||
public Region region(String ipAddress) {
|
||||
if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
|
||||
return new Region("local");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package org.dromara.maxkey.ip2location;
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IP转换区域地址解析
|
||||
*
|
||||
* <p>
|
||||
* 依次顺序为Local(本地) ->OnLine(在线解析) ->OffLine(离线解析) -> unknown(未知)
|
||||
* </p>
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
public class IpLocationParser extends AbstractIpLocation implements IpLocation{
|
||||
|
||||
IpLocation ipRegionLocal = new IpLocationLocal();
|
||||
|
||||
IpLocation ipLocationOnLine;
|
||||
|
||||
IpLocation ipLocationOffLine;
|
||||
|
||||
boolean isIpLocation;
|
||||
|
||||
|
||||
public IpLocationParser() {
|
||||
}
|
||||
|
||||
|
||||
public IpLocationParser(boolean isIpLocation,IpLocation ipLocationOnLine, IpLocation ipLocationOffLine) {
|
||||
super();
|
||||
this.ipLocationOnLine = ipLocationOnLine;
|
||||
this.ipLocationOffLine = ipLocationOffLine;
|
||||
this.isIpLocation = isIpLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* ip转换区域地址
|
||||
*/
|
||||
@Override
|
||||
public Region region(String ipAddress) {
|
||||
Region region = null;
|
||||
if( isIpLocation ){//true 需要转换,否则跳过
|
||||
//本地转换
|
||||
region = ipRegionLocal.region(ipAddress);
|
||||
//在线转换
|
||||
if(ipLocationOnLine != null && region == null) {
|
||||
region = ipLocationOnLine.region(ipAddress);
|
||||
}
|
||||
//离线转换
|
||||
if(ipLocationOffLine != null && region == null) {
|
||||
region = ipLocationOffLine.region(ipAddress);
|
||||
}
|
||||
}
|
||||
//不转换或者未找到返回unknown
|
||||
return region == null ? new Region("unknown") : region;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.dromara.maxkey.ip2location;
|
||||
|
||||
/**
|
||||
* IP所属区域实体
|
||||
*
|
||||
* @author Crystal.sea
|
||||
*
|
||||
*/
|
||||
public class Region {
|
||||
|
||||
/**
|
||||
* 国家
|
||||
*/
|
||||
String country;
|
||||
|
||||
/**
|
||||
* 省/州
|
||||
*/
|
||||
String province;
|
||||
|
||||
/**
|
||||
* 城市
|
||||
*/
|
||||
String city;
|
||||
|
||||
/**
|
||||
* 区域位置
|
||||
*/
|
||||
String addr;
|
||||
|
||||
public Region() {
|
||||
|
||||
}
|
||||
|
||||
public Region(String addr) {
|
||||
this.addr = addr;
|
||||
}
|
||||
|
||||
public Region(String country, String province, String city, String addr) {
|
||||
super();
|
||||
this.country = country;
|
||||
this.province = province;
|
||||
this.city = city;
|
||||
this.addr = addr;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getProvince() {
|
||||
return province;
|
||||
}
|
||||
|
||||
public void setProvince(String province) {
|
||||
this.province = province;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getAddr() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
public void setAddr(String addr) {
|
||||
this.addr = addr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Region [country=");
|
||||
builder.append(country);
|
||||
builder.append(", province=");
|
||||
builder.append(province);
|
||||
builder.append(", city=");
|
||||
builder.append(city);
|
||||
builder.append(", addr=");
|
||||
builder.append(addr);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.maxkey.ip2location.offline;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import org.dromara.maxkey.ip2location.AbstractIpLocation;
|
||||
import org.dromara.maxkey.ip2location.IpLocation;
|
||||
import org.dromara.maxkey.ip2location.Region;
|
||||
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
import com.maxmind.geoip2.exception.GeoIp2Exception;
|
||||
import com.maxmind.geoip2.model.CityResponse;
|
||||
|
||||
public class GeoIP2V4 extends AbstractIpLocation implements IpLocation{
|
||||
|
||||
DatabaseReader databaseReader;
|
||||
|
||||
public GeoIP2V4(DatabaseReader databaseReader) {
|
||||
this.databaseReader = databaseReader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region region(String ipAddress) {
|
||||
try {
|
||||
//解析IP地址
|
||||
InetAddress inetAddress = InetAddress.getByName(ipAddress);
|
||||
// 获取查询结果
|
||||
CityResponse response = databaseReader.city(inetAddress);
|
||||
// 获取国家信息
|
||||
String country = response.getCountry().getNames().get("zh-CN");
|
||||
// 获取省份/州
|
||||
String state = response.getMostSpecificSubdivision().getNames().get("zh-CN");
|
||||
// 获取城市
|
||||
String city = response.getCity().getNames().get("zh-CN");
|
||||
return new Region(country , state , city , country +" " + state + " " + city);
|
||||
} catch (IOException | GeoIp2Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.maxkey.ip2location.offline;
|
||||
|
||||
import org.dromara.maxkey.ip2location.AbstractIpLocation;
|
||||
import org.dromara.maxkey.ip2location.IpLocation;
|
||||
import org.dromara.maxkey.ip2location.Region;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
|
||||
|
||||
/**
|
||||
* 基于ip2region离线库ip查询
|
||||
*
|
||||
* <p>
|
||||
* 官方文档:https://gitee.com/lionsoul/ip2region Apache-2.0
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Ip2region (2.0 - xdb) 是一个离线 IP 数据管理框架和定位库,支持亿级别的数据段,10微秒级别的查询性能,提供了许多主流编程语言的 xdb 数据管理引擎的实现。
|
||||
* </p>
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
public class Ip2regionV2 extends AbstractIpLocation implements IpLocation{
|
||||
|
||||
Searcher searcher;;
|
||||
|
||||
public Ip2regionV2(Searcher searcher) {
|
||||
this.searcher = searcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region region(String ipAddress) {
|
||||
try {
|
||||
String regionAddr = searcher.search(ipAddress);
|
||||
if(regionAddr.indexOf("内网IP")>-1) {
|
||||
return new Region("内网IP");
|
||||
}
|
||||
String[] regionAddrs =regionAddr.split("\\|");
|
||||
return new Region(regionAddrs[0],regionAddrs[2],regionAddrs[3],regionAddrs[0]+regionAddrs[2]+regionAddrs[3]);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.maxkey.ip2location.online;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.dromara.maxkey.ip2location.AbstractIpLocation;
|
||||
import org.dromara.maxkey.ip2location.IpLocation;
|
||||
import org.dromara.maxkey.ip2location.Region;
|
||||
import org.dromara.maxkey.util.JsonUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
/**
|
||||
* Ip138查询ip地址
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
public class Ip138 extends AbstractIpLocation implements IpLocation{
|
||||
|
||||
public static final String REGION_URL = "https://www.ip138.com/iplookup.asp?ip=%s&action=2";
|
||||
|
||||
public static final String BEGIN = "\"ip_c_list\":[";
|
||||
public static final String END = "], \"zg\":1};";
|
||||
|
||||
@Override
|
||||
public Region region(String ipAddress) {
|
||||
try {
|
||||
Document doc;
|
||||
doc = Jsoup.connect(String.format(REGION_URL, ipAddress))
|
||||
.timeout(TIMEOUT)
|
||||
.userAgent(USERAGENT)
|
||||
.header("Host", "www.ip138.com")
|
||||
.header("Referer", "https://www.ip138.com/")
|
||||
.header("sec-ch-ua", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"98\", \"Google Chrome\";v=\"98\"")
|
||||
.header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
|
||||
.get();
|
||||
String htmlData = doc.toString();
|
||||
String jsonData = htmlData.substring(htmlData.indexOf(BEGIN) + BEGIN.length() , htmlData.indexOf(END));
|
||||
Ip138Response response = JsonUtils.stringToObject(jsonData, Ip138Response.class);
|
||||
return response == null ? null : new Region(response.getCt(),response.getProv(),response.getCity(),getLocation(response.toString()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.maxkey.ip2location.online;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Ip138返回结果
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Ip138Response {
|
||||
|
||||
String ct;
|
||||
String prov;
|
||||
String city;
|
||||
String area;
|
||||
String yunyin;
|
||||
|
||||
public Ip138Response() {
|
||||
}
|
||||
public String getCt() {
|
||||
return ct;
|
||||
}
|
||||
public void setCt(String ct) {
|
||||
this.ct = ct;
|
||||
}
|
||||
public String getProv() {
|
||||
return prov;
|
||||
}
|
||||
public void setProv(String prov) {
|
||||
this.prov = prov;
|
||||
}
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
public String getArea() {
|
||||
return area;
|
||||
}
|
||||
public void setArea(String area) {
|
||||
this.area = area;
|
||||
}
|
||||
public String getYunyin() {
|
||||
return yunyin;
|
||||
}
|
||||
public void setYunyin(String yunyin) {
|
||||
this.yunyin = yunyin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(ct)
|
||||
.append(prov)
|
||||
.append(city)
|
||||
.append(area)
|
||||
.append(" ")
|
||||
.append(yunyin);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
Database and Contents Copyright (c) 2022 MaxMind, Inc.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 65 MiB |
@ -0,0 +1,3 @@
|
||||
Use of this MaxMind product is governed by MaxMind's GeoLite2 End User License Agreement, which can be viewed at https://www.maxmind.com/en/geolite2/eula.
|
||||
|
||||
This database incorporates GeoNames [https://www.geonames.org] geographical data, which is made available under the Creative Commons Attribution 4.0 License. To view a copy of this license, visit https://creativecommons.org/licenses/by/4.0/.
|
||||
@ -0,0 +1 @@
|
||||
Latitude and longitude are not precise and should not be used to identify a particular street address or household.
|
||||
Binary file not shown.
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.maxkey.ip2location;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
import com.maxmind.geoip2.exception.GeoIp2Exception;
|
||||
import com.maxmind.geoip2.model.CityResponse;
|
||||
|
||||
public class Geoip2Test {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
ClassPathResource resource = new ClassPathResource("/geoip2/GeoLite2-City.mmdb");
|
||||
String ip = "117.155.70.59";
|
||||
|
||||
if (!resource.getFile().exists()) {
|
||||
System.out.println("Error: Invalid GeoLite2-City.mmdb file, filePath:" + resource.getFile().getPath());
|
||||
|
||||
}
|
||||
// 读取数据库内容
|
||||
DatabaseReader reader = null;
|
||||
try {
|
||||
reader = new DatabaseReader.Builder(resource.getFile()).build();
|
||||
//解析IP地址
|
||||
InetAddress ipAddress = InetAddress.getByName(ip);
|
||||
// 获取查询结果
|
||||
CityResponse response = reader.city(ipAddress);
|
||||
// 获取国家信息
|
||||
String country = response.getCountry().getNames().get("zh-CN");
|
||||
// 获取省份
|
||||
String state = response.getMostSpecificSubdivision().getNames().get("zh-CN");
|
||||
//查询不到时保持与ip2region方式的返回结果一致
|
||||
if (state == null){
|
||||
state = "0";
|
||||
}
|
||||
// 获取城市
|
||||
String city = response.getCity().getNames().get("zh-CN");
|
||||
if (city == null){
|
||||
city = "0";
|
||||
}
|
||||
String[] resu = {state,city};
|
||||
System.out.println(" " +country+" " +state +" " +city);
|
||||
} catch (IOException | GeoIp2Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.dromara.maxkey.ip2location;
|
||||
|
||||
import org.dromara.maxkey.ip2location.offline.Ip2regionV2;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
public class Ip2RegionV2Test {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
String ip ="101.227.131.220";
|
||||
ClassPathResource resource = new ClassPathResource("/ip2region/ip2region.xdb");
|
||||
byte[] dbBinStr = StreamUtils.copyToByteArray(resource.getInputStream());
|
||||
System.out.println(dbBinStr.length);
|
||||
//_logger.debug("ip2region length {}",dbBinStr.length);
|
||||
Searcher searcher = Searcher.newWithBuffer(dbBinStr);
|
||||
Ip2regionV2 ipRegionV2OffLine = new Ip2regionV2(searcher);
|
||||
String region = ipRegionV2OffLine.region(ip).toString();
|
||||
System.out.println(region);
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.maxkey.ip2location;
|
||||
|
||||
|
||||
import org.dromara.maxkey.ip2location.IpLocation;
|
||||
import org.dromara.maxkey.ip2location.online.Ip138;
|
||||
import org.junit.Test;
|
||||
|
||||
public class IpRegionIp138Test {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
IpLocation ipRegion = new Ip138();
|
||||
System.out.println(ipRegion.region("117.155.70.59"));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.maxkey.ip2location;
|
||||
|
||||
import org.dromara.maxkey.ip2location.IpLocationParser;
|
||||
import org.dromara.maxkey.ip2location.online.Ip138;
|
||||
import org.junit.Test;
|
||||
|
||||
public class IpRegionParserTest {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
System.out.println(
|
||||
new IpLocationParser().region("127.0.0.1")
|
||||
);
|
||||
|
||||
System.out.println(
|
||||
new IpLocationParser(true,new Ip138(),null).region("117.155.70.59")
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -28,6 +28,7 @@ include (
|
||||
//authentications
|
||||
'maxkey-authentications:maxkey-authentication-core',
|
||||
'maxkey-authentications:maxkey-authentication-captcha',
|
||||
'maxkey-authentications:maxkey-authentication-ip2location',
|
||||
'maxkey-authentications:maxkey-authentication-social',
|
||||
'maxkey-authentications:maxkey-authentication-otp',
|
||||
'maxkey-authentications:maxkey-authentication-provider',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user