添加用户归属地
This commit is contained in:
@@ -55,10 +55,10 @@ public class AppUserController {
|
|||||||
try {
|
try {
|
||||||
String token = userService.login(request.getAccount(), request.getPassword());
|
String token = userService.login(request.getAccount(), request.getPassword());
|
||||||
|
|
||||||
// 更新登录IP
|
// 更新登录IP和归属地
|
||||||
AppUser user = userService.getByAccount(request.getAccount());
|
AppUser user = userService.getByAccount(request.getAccount());
|
||||||
String loginIp = IpUtil.getClientIp(httpRequest);
|
String loginIp = IpUtil.getClientIp(httpRequest);
|
||||||
userService.updateLoginIp(user.getId(), loginIp);
|
userService.updateLoginInfo(user.getId(), loginIp);
|
||||||
|
|
||||||
Map<String, Object> data = new HashMap<>();
|
Map<String, Object> data = new HashMap<>();
|
||||||
data.put("token", token);
|
data.put("token", token);
|
||||||
@@ -75,7 +75,7 @@ public class AppUserController {
|
|||||||
* 用户注册(需要验证码)
|
* 用户注册(需要验证码)
|
||||||
*/
|
*/
|
||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
public Result<String> register(@RequestBody RegisterRequest request) {
|
public Result<String> register(@RequestBody RegisterRequest request, HttpServletRequest httpRequest) {
|
||||||
try {
|
try {
|
||||||
AppUser user = new AppUser();
|
AppUser user = new AppUser();
|
||||||
user.setUsername(request.getUsername());
|
user.setUsername(request.getUsername());
|
||||||
@@ -84,7 +84,9 @@ public class AppUserController {
|
|||||||
user.setTelephone(request.getTelephone());
|
user.setTelephone(request.getTelephone());
|
||||||
user.setAvatar(request.getAvatar());
|
user.setAvatar(request.getAvatar());
|
||||||
|
|
||||||
userService.register(user, request.getCode());
|
// 获取注册IP
|
||||||
|
String registerIp = IpUtil.getClientIp(httpRequest);
|
||||||
|
userService.register(user, request.getCode(), registerIp);
|
||||||
return Result.success("注册成功");
|
return Result.success("注册成功");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return Result.error(e.getMessage());
|
return Result.error(e.getMessage());
|
||||||
|
|||||||
@@ -54,9 +54,10 @@ public interface AppUserService extends IService<AppUser> {
|
|||||||
*
|
*
|
||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
* @param code 验证码
|
* @param code 验证码
|
||||||
|
* @param registerIp 注册IP
|
||||||
* @return 是否成功
|
* @return 是否成功
|
||||||
*/
|
*/
|
||||||
boolean register(AppUser user, String code);
|
boolean register(AppUser user, String code, String registerIp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新登录IP
|
* 更新登录IP
|
||||||
@@ -65,4 +66,12 @@ public interface AppUserService extends IService<AppUser> {
|
|||||||
* @param loginIp 登录IP
|
* @param loginIp 登录IP
|
||||||
*/
|
*/
|
||||||
void updateLoginIp(Long userId, String loginIp);
|
void updateLoginIp(Long userId, String loginIp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新登录信息(IP和归属地)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param loginIp 登录IP
|
||||||
|
*/
|
||||||
|
void updateLoginInfo(Long userId, String loginIp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.corewing.app.entity.AppUser;
|
|||||||
import com.corewing.app.mapper.AppUserMapper;
|
import com.corewing.app.mapper.AppUserMapper;
|
||||||
import com.corewing.app.service.AppUserService;
|
import com.corewing.app.service.AppUserService;
|
||||||
import com.corewing.app.service.VerifyCodeService;
|
import com.corewing.app.service.VerifyCodeService;
|
||||||
|
import com.corewing.app.util.Ip2RegionUtil;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.DigestUtils;
|
import org.springframework.util.DigestUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -20,9 +21,11 @@ import java.nio.charset.StandardCharsets;
|
|||||||
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {
|
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {
|
||||||
|
|
||||||
private final VerifyCodeService verifyCodeService;
|
private final VerifyCodeService verifyCodeService;
|
||||||
|
private final Ip2RegionUtil ip2RegionUtil;
|
||||||
|
|
||||||
public AppUserServiceImpl(VerifyCodeService verifyCodeService) {
|
public AppUserServiceImpl(VerifyCodeService verifyCodeService, Ip2RegionUtil ip2RegionUtil) {
|
||||||
this.verifyCodeService = verifyCodeService;
|
this.verifyCodeService = verifyCodeService;
|
||||||
|
this.ip2RegionUtil = ip2RegionUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -92,7 +95,7 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean register(AppUser user, String code) {
|
public boolean register(AppUser user, String code, String registerIp) {
|
||||||
// 检查用户名是否已存在
|
// 检查用户名是否已存在
|
||||||
AppUser existUser = getByUsername(user.getUsername());
|
AppUser existUser = getByUsername(user.getUsername());
|
||||||
if (existUser != null) {
|
if (existUser != null) {
|
||||||
@@ -136,6 +139,12 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
|
|||||||
user.setStatus(1);
|
user.setStatus(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置注册IP和归属地
|
||||||
|
if (StringUtils.hasText(registerIp)) {
|
||||||
|
user.setRegisterIp(registerIp);
|
||||||
|
user.setRegisterRegion(ip2RegionUtil.getRegion(registerIp));
|
||||||
|
}
|
||||||
|
|
||||||
// 保存用户
|
// 保存用户
|
||||||
return this.save(user);
|
return this.save(user);
|
||||||
}
|
}
|
||||||
@@ -147,4 +156,13 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
|
|||||||
user.setLoginIp(loginIp);
|
user.setLoginIp(loginIp);
|
||||||
this.updateById(user);
|
this.updateById(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLoginInfo(Long userId, String loginIp) {
|
||||||
|
AppUser user = new AppUser();
|
||||||
|
user.setId(userId);
|
||||||
|
user.setLoginIp(loginIp);
|
||||||
|
user.setLoginRegion(ip2RegionUtil.getRegion(loginIp));
|
||||||
|
this.updateById(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
179
src/main/java/com/corewing/app/util/Ip2RegionUtil.java
Normal file
179
src/main/java/com/corewing/app/util/Ip2RegionUtil.java
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
package com.corewing.app.util;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.lionsoul.ip2region.xdb.Searcher;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP 归属地查询工具类
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class Ip2RegionUtil {
|
||||||
|
|
||||||
|
private Searcher searcher;
|
||||||
|
private byte[] vIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 IP2Region 搜索器
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
try {
|
||||||
|
// 从 classpath 加载 xdb 文件
|
||||||
|
ClassPathResource resource = new ClassPathResource("ipdb/ip2region.xdb");
|
||||||
|
InputStream inputStream = resource.getInputStream();
|
||||||
|
|
||||||
|
// 将 InputStream 转换为 byte[]
|
||||||
|
vIndex = new byte[inputStream.available()];
|
||||||
|
inputStream.read(vIndex);
|
||||||
|
inputStream.close();
|
||||||
|
|
||||||
|
// 创建 searcher 对象
|
||||||
|
searcher = Searcher.newWithBuffer(vIndex);
|
||||||
|
log.info("IP2Region 初始化成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("IP2Region 初始化失败: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 IP 地址查询归属地
|
||||||
|
*
|
||||||
|
* @param ip IP 地址
|
||||||
|
* @return 归属地信息,格式:国家|区域|省份|城市|ISP
|
||||||
|
*/
|
||||||
|
public String getRegion(String ip) {
|
||||||
|
if (ip == null || ip.trim().isEmpty()) {
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤本地 IP
|
||||||
|
if (isLocalIp(ip)) {
|
||||||
|
return "局域网";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (searcher == null) {
|
||||||
|
log.warn("IP2Region 搜索器未初始化");
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
String region = searcher.search(ip);
|
||||||
|
return formatRegion(region);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询 IP 归属地失败, IP: {}, 异常: {}", ip, e.getMessage());
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化归属地信息
|
||||||
|
* 原始格式:国家|区域|省份|城市|ISP
|
||||||
|
* 格式化后:省份-城市
|
||||||
|
*
|
||||||
|
* @param region 原始归属地信息
|
||||||
|
* @return 格式化后的归属地
|
||||||
|
*/
|
||||||
|
private String formatRegion(String region) {
|
||||||
|
if (region == null || region.trim().isEmpty()) {
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String[] parts = region.split("\\|");
|
||||||
|
if (parts.length < 5) {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
String country = parts[0];
|
||||||
|
String province = parts[2];
|
||||||
|
String city = parts[3];
|
||||||
|
|
||||||
|
// 处理国内 IP
|
||||||
|
if ("中国".equals(country)) {
|
||||||
|
// 如果省份和城市相同,只返回省份
|
||||||
|
if (province.equals(city)) {
|
||||||
|
return province;
|
||||||
|
}
|
||||||
|
// 如果省份或城市为 0,说明数据不完整
|
||||||
|
if ("0".equals(province) || "0".equals(city)) {
|
||||||
|
return "中国";
|
||||||
|
}
|
||||||
|
return province + "-" + city;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理国外 IP
|
||||||
|
if (!"0".equals(country) && !country.isEmpty()) {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "未知";
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("格式化归属地信息失败: {}", region, e);
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为本地 IP
|
||||||
|
*
|
||||||
|
* @param ip IP 地址
|
||||||
|
* @return 是否为本地 IP
|
||||||
|
*/
|
||||||
|
private boolean isLocalIp(String ip) {
|
||||||
|
return ip.startsWith("127.") ||
|
||||||
|
ip.startsWith("192.168.") ||
|
||||||
|
ip.startsWith("10.") ||
|
||||||
|
ip.startsWith("172.16.") ||
|
||||||
|
ip.startsWith("172.17.") ||
|
||||||
|
ip.startsWith("172.18.") ||
|
||||||
|
ip.startsWith("172.19.") ||
|
||||||
|
ip.startsWith("172.20.") ||
|
||||||
|
ip.startsWith("172.21.") ||
|
||||||
|
ip.startsWith("172.22.") ||
|
||||||
|
ip.startsWith("172.23.") ||
|
||||||
|
ip.startsWith("172.24.") ||
|
||||||
|
ip.startsWith("172.25.") ||
|
||||||
|
ip.startsWith("172.26.") ||
|
||||||
|
ip.startsWith("172.27.") ||
|
||||||
|
ip.startsWith("172.28.") ||
|
||||||
|
ip.startsWith("172.29.") ||
|
||||||
|
ip.startsWith("172.30.") ||
|
||||||
|
ip.startsWith("172.31.") ||
|
||||||
|
"localhost".equalsIgnoreCase(ip) ||
|
||||||
|
"0:0:0:0:0:0:0:1".equals(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取完整的归属地信息(用于调试)
|
||||||
|
*
|
||||||
|
* @param ip IP 地址
|
||||||
|
* @return 完整的归属地信息
|
||||||
|
*/
|
||||||
|
public String getFullRegion(String ip) {
|
||||||
|
if (ip == null || ip.trim().isEmpty()) {
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLocalIp(ip)) {
|
||||||
|
return "局域网";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (searcher == null) {
|
||||||
|
log.warn("IP2Region 搜索器未初始化");
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
return searcher.search(ip);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询 IP 归属地失败, IP: {}, 异常: {}", ip, e.getMessage());
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/main/resources/ipdb/ip2region.xdb
Normal file
BIN
src/main/resources/ipdb/ip2region.xdb
Normal file
Binary file not shown.
Reference in New Issue
Block a user