ip隔离-实现

This commit is contained in:
khalil
2023-11-20 16:34:16 +08:00
parent 3a6b3f515a
commit 3bf967648b
10 changed files with 139 additions and 8 deletions

View File

@@ -29,6 +29,8 @@ public class RegionService {
private final String CHINA = "中國";
private final String HK = "香港";
private final String MO = "澳門";
private final String TW = "台灣省";
public List<String> getConfig() {
String configStr = sysConfService.getSysConfValueById(Constant.SysConfId.USER_REGION_CONFIG);
@@ -77,4 +79,13 @@ public class RegionService {
String dbRegion = regionSearchService.getRegion(registerIp);
return ZhConverterUtil.toTraditional(dbRegion);
}
public boolean isChineseMainland(String ipRegion){
String[] ipRegionArray = ipRegion.split("\\|");
return CHINA.equals(ipRegionArray[0])
&& !HK.equals(ipRegionArray[1])
&& !MO.equals(ipRegionArray[1])
&& !TW.equals(ipRegionArray[1]);
}
}

View File

@@ -8,7 +8,7 @@ public enum BusiStatus implements BusiStatusInterface {
SUCCESS(200, "success"), //成功
NOTEXISTS(404, "不存在"),
IP_REGION_HAD_LIMIT(401, "該地區已被限制訪問"),
IP_REGION_HAD_LIMIT(401, "該地區暫未開放使用"),
NOAUTHORITY(401, "沒有權限"),
FROZEN_USER(402, "賬號已被凍結,請聯繫官方客服"),
ACCOUNT_ERROR(407, "用戶賬號異常,請聯繫官方客服"),//賬號異常-賬號被封

View File

@@ -1,6 +1,8 @@
package com.accompany.common.constant;
import com.google.common.collect.Lists;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
@@ -6017,6 +6019,12 @@ public class Constant {
public static final Byte AGREE = 1;//同意
}
/**
* 中国大陆运营商代码
*/
public final static String CHINA_MAINLAND_MCC_CODE = "460";
public final static List<String> CHINA_MAINLAND_LANG_CODES = Lists.newArrayList("zh-hans", "zh-cn");
/**
* 中国大陆区号
*/

View File

@@ -1,12 +1,16 @@
package com.accompany.business.model.ip;
import com.accompany.common.device.DeviceInfo;
import com.accompany.core.mybatis.typehandler.StringListTypeHandler;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.List;
@Data
public class IpRegionLimitRecord {
@@ -14,8 +18,11 @@ public class IpRegionLimitRecord {
@TableId(type = IdType.AUTO)
private Long uid;
private String phone;
private Date createTime;
private Date lastCheckTime;
private String lastCheckIp;
private String lastCheckIpRegion;
private Date lastCheckTime;
@TableField(typeHandler = StringListTypeHandler.class)
private List<String> deviceIds;
}

View File

@@ -3,8 +3,13 @@ package com.accompany.business.mybatismapper.ip;
import com.accompany.business.model.ip.IpRegionWhite;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface IpRegionWhiteMapper extends BaseMapper<IpRegionWhite> {
boolean isInIpRegionWhileListByUidOrPhone(@Param("uid") Long uid, @Param("phone") String phone);
boolean isInIpRegionWhileListByUid(@Param("uid") Long uid);
}

View File

@@ -2,17 +2,58 @@ package com.accompany.business.service.ip;
import com.accompany.business.model.ip.IpRegionLimitRecord;
import com.accompany.business.mybatismapper.ip.IpRegionLimitRecordMapper;
import com.accompany.core.base.SpringContextHolder;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class IpRegionLimitRecordService extends ServiceImpl<IpRegionLimitRecordMapper, IpRegionLimitRecord> {
public boolean isInLimitRecord(Long uid) {
public boolean isInLimitRecord(Long uid, String ip, String ipRegion, String deviceId) {
IpRegionLimitRecord record = getById(uid);
if (null == record){
return true;
}
record.setLastCheckIp(ip);
record.setLastCheckIpRegion(ipRegion);
record.setLastCheckTime(new Date());
List<String> deviceIds = record.getDeviceIds();
if (null == deviceIds){
deviceIds = new ArrayList<>();
}
if (!deviceIds.contains(deviceId)){
deviceIds.add(deviceId);
}
record.setDeviceIds(deviceIds);
SpringContextHolder.getBean(IpRegionLimitRecordService.class).update(record);
return false;
}
@Async
public void update(IpRegionLimitRecord record){
updateById(record);
}
@Async
public void save(Long uid, String phone, String ip, String ipRegion, String deviceId) {
Date now = new Date();
IpRegionLimitRecord record = new IpRegionLimitRecord();
record.setUid(uid);
record.setPhone(phone);
record.setCreateTime(now);
record.setLastCheckTime(now);
record.setLastCheckIp(ip);
record.setLastCheckIpRegion(ipRegion);
List<String> deviceIds = new ArrayList<>();
deviceIds.add(deviceId);
record.setDeviceIds(deviceIds);
save(record);
}
}

View File

@@ -3,11 +3,14 @@ package com.accompany.business.service.ip;
import com.accompany.common.constant.Constant;
import com.accompany.common.device.DeviceInfo;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.CommonUtil;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Account;
import com.accompany.core.service.SysConfService;
import com.accompany.core.service.account.AccountService;
import com.accompany.core.service.region.RegionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -23,21 +26,60 @@ public class IpRegionService {
private IpRegionWhiteService whiteService;
@Autowired
private AccountService accountService;
@Autowired
private RegionService regionService;
public Long check(Long uid, String ip, DeviceInfo deviceInfo) {
if (recordService.isInLimitRecord(uid)){
String ipRegion = regionService.getRegion(ip);
if (recordService.isInLimitRecord(uid, ip, ipRegion, deviceInfo.getDeviceId())){
log.error("[ipRegionCheck] 被拦截,已在限制访问记录中 uid {} ip {} ipRegion {} deviceId {} mcc {} lang {}",
uid, ip, ipRegion, deviceInfo.getDeviceId(), deviceInfo.getMcc(), deviceInfo.getLang());
throw new ServiceException(BusiStatus.IP_REGION_HAD_LIMIT);
}
Account account = accountService.getAccountByUid(uid);
if (null == account){
throw new ServiceException(BusiStatus.ACCOUNT_NOT_EXISTS);
log.error("[ipRegionCheck] 被拦截找不到uid对应的account uid {} ip {} ipRegion {} deviceId {} mcc {} lang {}",
uid, ip, ipRegion, deviceInfo.getDeviceId(), deviceInfo.getMcc(), deviceInfo.getLang());
throw new ServiceException(BusiStatus.IP_REGION_HAD_LIMIT);
}
if (whiteService.isInWhileList(account.getUid(), account.getPhone())){
return getNextTimestampInterval();
}
if (CommonUtil.checkPhoneFormat(account.getPhoneAreaCode(), account.getPhone())
&& Constant.CHINA_MAINLAND_PHONE_AREA_CODE.equals(account.getPhoneAreaCode())){
log.error("[ipRegionCheck] 被拦截手机区号是86 uid {} ip {} ipRegion {} deviceId {} mcc {} lang {}",
uid, ip, ipRegion, deviceInfo.getDeviceId(), deviceInfo.getMcc(), deviceInfo.getLang());
recordService.save(uid, account.getPhone(), ip, ipRegion, deviceInfo.getDeviceId());
throw new ServiceException(BusiStatus.IP_REGION_HAD_LIMIT);
}
if (regionService.isChineseMainland(ipRegion)){
log.error("[ipRegionCheck] 被拦截ip为中国大陆 ip uid {} ip {} ipRegion {} deviceId {} mcc {} lang {}",
uid, ip, ipRegion, deviceInfo.getDeviceId(), deviceInfo.getMcc(), deviceInfo.getLang());
recordService.save(uid, account.getPhone(), ip, ipRegion, deviceInfo.getDeviceId());
throw new ServiceException(BusiStatus.IP_REGION_HAD_LIMIT);
}
if (StringUtils.isNotBlank(deviceInfo.getMcc())
&& Constant.CHINA_MAINLAND_MCC_CODE.equals(account.getPhoneAreaCode())){
log.error("[ipRegionCheck] 被拦截mcc为大陆运营商 ip uid {} ip {} ipRegion {} deviceId {} mcc {} lang {}",
uid, ip, ipRegion, deviceInfo.getDeviceId(), deviceInfo.getMcc(), deviceInfo.getLang());
recordService.save(uid, account.getPhone(), ip, ipRegion, deviceInfo.getDeviceId());
throw new ServiceException(BusiStatus.IP_REGION_HAD_LIMIT);
}
if (StringUtils.isNotBlank(deviceInfo.getLang())
&& Constant.CHINA_MAINLAND_LANG_CODES.contains(deviceInfo.getLang().toLowerCase())){
log.error("[ipRegionCheck] 被拦截,系统语言为中文简体 ip uid {} ip {} ipRegion {} deviceId {} mcc {} lang {}",
uid, ip, ipRegion, deviceInfo.getDeviceId(), deviceInfo.getMcc(), deviceInfo.getLang());
recordService.save(uid, account.getPhone(), ip, ipRegion, deviceInfo.getDeviceId());
throw new ServiceException(BusiStatus.IP_REGION_HAD_LIMIT);
}
return getNextTimestampInterval();
}
@@ -45,4 +87,5 @@ public class IpRegionService {
long nextHour = Long.parseLong(sysConfService.getDefaultSysConfValueById(Constant.SysConfId.MAINLAND_IP_IOS_INTERVAL_HOUR, "1"));
return nextHour * 60 * 60 * 1000;
}
}

View File

@@ -2,6 +2,7 @@ package com.accompany.business.service.ip;
import com.accompany.business.model.ip.IpRegionWhite;
import com.accompany.business.mybatismapper.ip.IpRegionWhiteMapper;
import com.accompany.common.utils.CommonUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -11,6 +12,10 @@ import org.springframework.stereotype.Service;
public class IpRegionWhiteService extends ServiceImpl<IpRegionWhiteMapper, IpRegionWhite> {
public boolean isInWhileList(Long uid, String phone) {
return true;
if (CommonUtil.checkValidPhone(phone)){
return baseMapper.isInIpRegionWhileListByUidOrPhone(uid, phone);
}
return baseMapper.isInIpRegionWhileListByUid(uid);
}
}

View File

@@ -1,4 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.accompany.business.mybatismapper.ip.IpRegionWhiteMapper">
<select id="isInIpRegionWhileListByUidOrPhone" resultType="java.lang.Boolean">
select count(*)
from (select id from ip_region_white where uid = #{uid}
union
select id from ip_region_white where phone = #{phone}
) a
</select>
<select id="isInIpRegionWhileListByUid" resultType="java.lang.Boolean">
select count(*) from ip_region_white where uid = #{uid}
</select>
</mapper>

View File

@@ -27,7 +27,7 @@ public class IpRegionController extends BaseController {
})
@Authorization
@PostMapping("/check")
private BusiResult<Long> check(HttpServletRequest request){
private BusiResult<Long> check(HttpServletRequest request, String mcc, String lang){
Long uid = getUid(request);
DeviceInfo deviceInfo = getDeviceInfo(request);
String ip = IPUtils.getRealIpAddress(request);