13 changed files with 1370 additions and 11 deletions
@ -0,0 +1,449 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace CellularManagement.Domain.Common.Attributes; |
|||
|
|||
/// <summary>
|
|||
/// IMSI验证特性
|
|||
/// 确保IMSI是15位数字,并且符合IMSI格式要求
|
|||
/// </summary>
|
|||
public class IMSIValidationAttribute : ValidationAttribute |
|||
{ |
|||
/// <summary>
|
|||
/// 验证IMSI格式
|
|||
/// </summary>
|
|||
/// <param name="value">要验证的值</param>
|
|||
/// <returns>验证结果</returns>
|
|||
public override bool IsValid(object? value) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var imsi = value.ToString(); |
|||
if (string.IsNullOrWhiteSpace(imsi)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// 检查长度是否为15位
|
|||
if (imsi.Length != 15) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// 检查是否全部为数字
|
|||
if (!imsi.All(char.IsDigit)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// 检查MCC(移动国家代码)是否有效(前3位)
|
|||
var mcc = imsi.Substring(0, 3); |
|||
if (!IsValidMCC(mcc)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// 检查MNC(移动网络代码)是否有效(第4-5位或第4-6位)
|
|||
var mnc = GetMNC(imsi); |
|||
if (!IsValidMNC(mnc)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取验证错误消息
|
|||
/// </summary>
|
|||
/// <param name="name">属性名称</param>
|
|||
/// <returns>错误消息</returns>
|
|||
public override string FormatErrorMessage(string name) |
|||
{ |
|||
return $"{name}必须是15位数字,且符合IMSI格式要求(MCC+MNC+MSIN)"; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 验证MCC(移动国家代码)是否有效
|
|||
/// </summary>
|
|||
/// <param name="mcc">MCC代码</param>
|
|||
/// <returns>是否有效</returns>
|
|||
private bool IsValidMCC(string mcc) |
|||
{ |
|||
// 常见的MCC代码验证
|
|||
var validMCCs = new[] |
|||
{ |
|||
"460", // 中国
|
|||
"466", // 台湾
|
|||
"455", // 澳门
|
|||
"454", // 香港
|
|||
"310", // 美国
|
|||
"311", // 美国
|
|||
"312", // 美国
|
|||
"313", // 美国
|
|||
"314", // 美国
|
|||
"315", // 美国
|
|||
"316", // 美国
|
|||
"234", // 英国
|
|||
"235", // 英国
|
|||
"238", // 丹麦
|
|||
"240", // 瑞典
|
|||
"242", // 挪威
|
|||
"244", // 芬兰
|
|||
"246", // 立陶宛
|
|||
"247", // 拉脱维亚
|
|||
"248", // 爱沙尼亚
|
|||
"250", // 俄罗斯
|
|||
"255", // 乌克兰
|
|||
"257", // 白俄罗斯
|
|||
"259", // 摩尔多瓦
|
|||
"260", // 波兰
|
|||
"262", // 德国
|
|||
"268", // 葡萄牙
|
|||
"270", // 卢森堡
|
|||
"272", // 爱尔兰
|
|||
"274", // 冰岛
|
|||
"276", // 阿尔巴尼亚
|
|||
"278", // 马耳他
|
|||
"280", // 塞浦路斯
|
|||
"282", // 格鲁吉亚
|
|||
"283", // 亚美尼亚
|
|||
"284", // 保加利亚
|
|||
"286", // 土耳其
|
|||
"288", // 法罗群岛
|
|||
"290", // 格陵兰
|
|||
"292", // 安道尔
|
|||
"293", // 斯洛文尼亚
|
|||
"294", // 北马其顿
|
|||
"295", // 列支敦士登
|
|||
"297", // 黑山
|
|||
"302", // 加拿大
|
|||
"334", // 墨西哥
|
|||
"338", // 牙买加
|
|||
"340", // 瓜德罗普
|
|||
"342", // 巴巴多斯
|
|||
"344", // 安提瓜和巴布达
|
|||
"346", // 开曼群岛
|
|||
"348", // 英属维尔京群岛
|
|||
"350", // 百慕大
|
|||
"352", // 格林纳达
|
|||
"354", // 蒙特塞拉特
|
|||
"356", // 圣基茨和尼维斯
|
|||
"358", // 圣卢西亚
|
|||
"360", // 圣文森特和格林纳丁斯
|
|||
"362", // 荷属安的列斯
|
|||
"363", // 阿鲁巴
|
|||
"364", // 巴哈马
|
|||
"365", // 安圭拉
|
|||
"366", // 多米尼克
|
|||
"368", // 古巴
|
|||
"370", // 多米尼加共和国
|
|||
"372", // 海地
|
|||
"374", // 特立尼达和多巴哥
|
|||
"376", // 特克斯和凯科斯群岛
|
|||
"400", // 阿塞拜疆
|
|||
"401", // 哈萨克斯坦
|
|||
"402", // 不丹
|
|||
"404", // 印度
|
|||
"405", // 印度
|
|||
"406", // 印度
|
|||
"410", // 巴基斯坦
|
|||
"412", // 阿富汗
|
|||
"413", // 斯里兰卡
|
|||
"414", // 缅甸
|
|||
"415", // 黎巴嫩
|
|||
"416", // 约旦
|
|||
"417", // 叙利亚
|
|||
"418", // 伊拉克
|
|||
"419", // 科威特
|
|||
"420", // 沙特阿拉伯
|
|||
"421", // 也门
|
|||
"422", // 阿曼
|
|||
"424", // 阿联酋
|
|||
"425", // 以色列
|
|||
"426", // 巴林
|
|||
"427", // 卡塔尔
|
|||
"428", // 蒙古
|
|||
"429", // 尼泊尔
|
|||
"430", // 阿联酋
|
|||
"431", // 阿联酋
|
|||
"432", // 伊朗
|
|||
"434", // 乌兹别克斯坦
|
|||
"436", // 塔吉克斯坦
|
|||
"437", // 吉尔吉斯斯坦
|
|||
"438", // 土库曼斯坦
|
|||
"440", // 日本
|
|||
"441", // 日本
|
|||
"450", // 韩国
|
|||
"452", // 越南
|
|||
"454", // 香港
|
|||
"455", // 澳门
|
|||
"456", // 柬埔寨
|
|||
"457", // 老挝
|
|||
"460", // 中国
|
|||
"466", // 台湾
|
|||
"467", // 朝鲜
|
|||
"470", // 孟加拉国
|
|||
"472", // 马尔代夫
|
|||
"502", // 马来西亚
|
|||
"505", // 澳大利亚
|
|||
"510", // 印度尼西亚
|
|||
"514", // 东帝汶
|
|||
"515", // 菲律宾
|
|||
"520", // 泰国
|
|||
"525", // 新加坡
|
|||
"528", // 文莱
|
|||
"530", // 新西兰
|
|||
"534", // 北马里亚纳群岛
|
|||
"535", // 关岛
|
|||
"536", // 瑙鲁
|
|||
"537", // 巴布亚新几内亚
|
|||
"539", // 汤加
|
|||
"540", // 所罗门群岛
|
|||
"541", // 瓦努阿图
|
|||
"542", // 斐济
|
|||
"543", // 瓦利斯和富图纳
|
|||
"544", // 美属萨摩亚
|
|||
"545", // 基里巴斯
|
|||
"546", // 新喀里多尼亚
|
|||
"547", // 法属波利尼西亚
|
|||
"548", // 库克群岛
|
|||
"549", // 萨摩亚
|
|||
"550", // 密克罗尼西亚联邦
|
|||
"552", // 帕劳
|
|||
"553", // 图瓦卢
|
|||
"554", // 托克劳
|
|||
"555", // 纽埃
|
|||
"602", // 埃及
|
|||
"603", // 阿尔及利亚
|
|||
"604", // 摩洛哥
|
|||
"605", // 突尼斯
|
|||
"606", // 利比亚
|
|||
"607", // 冈比亚
|
|||
"608", // 塞内加尔
|
|||
"609", // 毛里塔尼亚
|
|||
"610", // 马里
|
|||
"611", // 几内亚
|
|||
"612", // 科特迪瓦
|
|||
"613", // 布基纳法索
|
|||
"614", // 尼日尔
|
|||
"615", // 多哥
|
|||
"616", // 贝宁
|
|||
"617", // 毛里求斯
|
|||
"618", // 利比里亚
|
|||
"619", // 塞拉利昂
|
|||
"620", // 加纳
|
|||
"621", // 尼日利亚
|
|||
"622", // 乍得
|
|||
"623", // 中非共和国
|
|||
"624", // 喀麦隆
|
|||
"625", // 佛得角
|
|||
"626", // 圣多美和普林西比
|
|||
"627", // 赤道几内亚
|
|||
"628", // 加蓬
|
|||
"629", // 刚果共和国
|
|||
"630", // 刚果民主共和国
|
|||
"631", // 安哥拉
|
|||
"632", // 几内亚比绍
|
|||
"633", // 塞舌尔
|
|||
"634", // 苏丹
|
|||
"635", // 卢旺达
|
|||
"636", // 埃塞俄比亚
|
|||
"637", // 索马里
|
|||
"638", // 吉布提
|
|||
"639", // 肯尼亚
|
|||
"640", // 坦桑尼亚
|
|||
"641", // 乌干达
|
|||
"642", // 布隆迪
|
|||
"643", // 莫桑比克
|
|||
"645", // 赞比亚
|
|||
"646", // 马达加斯加
|
|||
"647", // 留尼汪
|
|||
"648", // 津巴布韦
|
|||
"649", // 纳米比亚
|
|||
"650", // 马拉维
|
|||
"651", // 莱索托
|
|||
"652", // 博茨瓦纳
|
|||
"653", // 斯威士兰
|
|||
"654", // 科摩罗
|
|||
"655", // 南非
|
|||
"657", // 厄立特里亚
|
|||
"659", // 南苏丹
|
|||
"702", // 伯利兹
|
|||
"704", // 危地马拉
|
|||
"706", // 萨尔瓦多
|
|||
"708", // 洪都拉斯
|
|||
"710", // 尼加拉瓜
|
|||
"712", // 哥斯达黎加
|
|||
"714", // 巴拿马
|
|||
"716", // 秘鲁
|
|||
"722", // 阿根廷
|
|||
"724", // 巴西
|
|||
"730", // 智利
|
|||
"732", // 哥伦比亚
|
|||
"734", // 委内瑞拉
|
|||
"736", // 玻利维亚
|
|||
"738", // 圭亚那
|
|||
"740", // 厄瓜多尔
|
|||
"742", // 法属圭亚那
|
|||
"744", // 巴拉圭
|
|||
"746", // 苏里南
|
|||
"748", // 乌拉圭
|
|||
"750", // 福克兰群岛
|
|||
"901", // 国际海事卫星组织
|
|||
"902", // 国际海事卫星组织
|
|||
"903", // 国际海事卫星组织
|
|||
"904", // 国际海事卫星组织
|
|||
"905", // 国际海事卫星组织
|
|||
"906", // 国际海事卫星组织
|
|||
"907", // 国际海事卫星组织
|
|||
"908", // 国际海事卫星组织
|
|||
"909", // 国际海事卫星组织
|
|||
"910", // 国际海事卫星组织
|
|||
"911", // 国际海事卫星组织
|
|||
"912", // 国际海事卫星组织
|
|||
"913", // 国际海事卫星组织
|
|||
"914", // 国际海事卫星组织
|
|||
"915", // 国际海事卫星组织
|
|||
"916", // 国际海事卫星组织
|
|||
"917", // 国际海事卫星组织
|
|||
"918", // 国际海事卫星组织
|
|||
"919", // 国际海事卫星组织
|
|||
"920", // 国际海事卫星组织
|
|||
"921", // 国际海事卫星组织
|
|||
"922", // 国际海事卫星组织
|
|||
"923", // 国际海事卫星组织
|
|||
"924", // 国际海事卫星组织
|
|||
"925", // 国际海事卫星组织
|
|||
"926", // 国际海事卫星组织
|
|||
"927", // 国际海事卫星组织
|
|||
"928", // 国际海事卫星组织
|
|||
"929", // 国际海事卫星组织
|
|||
"930", // 国际海事卫星组织
|
|||
"931", // 国际海事卫星组织
|
|||
"932", // 国际海事卫星组织
|
|||
"933", // 国际海事卫星组织
|
|||
"934", // 国际海事卫星组织
|
|||
"935", // 国际海事卫星组织
|
|||
"936", // 国际海事卫星组织
|
|||
"937", // 国际海事卫星组织
|
|||
"938", // 国际海事卫星组织
|
|||
"939", // 国际海事卫星组织
|
|||
"940", // 国际海事卫星组织
|
|||
"941", // 国际海事卫星组织
|
|||
"942", // 国际海事卫星组织
|
|||
"943", // 国际海事卫星组织
|
|||
"944", // 国际海事卫星组织
|
|||
"945", // 国际海事卫星组织
|
|||
"946", // 国际海事卫星组织
|
|||
"947", // 国际海事卫星组织
|
|||
"948", // 国际海事卫星组织
|
|||
"949", // 国际海事卫星组织
|
|||
"950", // 国际海事卫星组织
|
|||
"951", // 国际海事卫星组织
|
|||
"952", // 国际海事卫星组织
|
|||
"953", // 国际海事卫星组织
|
|||
"954", // 国际海事卫星组织
|
|||
"955", // 国际海事卫星组织
|
|||
"956", // 国际海事卫星组织
|
|||
"957", // 国际海事卫星组织
|
|||
"958", // 国际海事卫星组织
|
|||
"959", // 国际海事卫星组织
|
|||
"960", // 国际海事卫星组织
|
|||
"961", // 国际海事卫星组织
|
|||
"962", // 国际海事卫星组织
|
|||
"963", // 国际海事卫星组织
|
|||
"964", // 国际海事卫星组织
|
|||
"965", // 国际海事卫星组织
|
|||
"966", // 国际海事卫星组织
|
|||
"967", // 国际海事卫星组织
|
|||
"968", // 国际海事卫星组织
|
|||
"969", // 国际海事卫星组织
|
|||
"970", // 国际海事卫星组织
|
|||
"971", // 国际海事卫星组织
|
|||
"972", // 国际海事卫星组织
|
|||
"973", // 国际海事卫星组织
|
|||
"974", // 国际海事卫星组织
|
|||
"975", // 国际海事卫星组织
|
|||
"976", // 国际海事卫星组织
|
|||
"977", // 国际海事卫星组织
|
|||
"978", // 国际海事卫星组织
|
|||
"979", // 国际海事卫星组织
|
|||
"980", // 国际海事卫星组织
|
|||
"981", // 国际海事卫星组织
|
|||
"982", // 国际海事卫星组织
|
|||
"983", // 国际海事卫星组织
|
|||
"984", // 国际海事卫星组织
|
|||
"985", // 国际海事卫星组织
|
|||
"986", // 国际海事卫星组织
|
|||
"987", // 国际海事卫星组织
|
|||
"988", // 国际海事卫星组织
|
|||
"989", // 国际海事卫星组织
|
|||
"990", // 国际海事卫星组织
|
|||
"991", // 国际海事卫星组织
|
|||
"992", // 国际海事卫星组织
|
|||
"993", // 国际海事卫星组织
|
|||
"994", // 国际海事卫星组织
|
|||
"995", // 国际海事卫星组织
|
|||
"996", // 国际海事卫星组织
|
|||
"997", // 国际海事卫星组织
|
|||
"998", // 国际海事卫星组织
|
|||
"999", // 国际海事卫星组织
|
|||
}; |
|||
|
|||
return validMCCs.Contains(mcc); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MNC(移动网络代码)
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>MNC代码</returns>
|
|||
private string GetMNC(string imsi) |
|||
{ |
|||
// 根据MCC确定MNC长度
|
|||
var mcc = imsi.Substring(0, 3); |
|||
|
|||
// 某些国家的MNC是3位,其他是2位
|
|||
var mncLength = GetMNCLength(mcc); |
|||
return imsi.Substring(3, mncLength); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MNC长度
|
|||
/// </summary>
|
|||
/// <param name="mcc">MCC代码</param>
|
|||
/// <returns>MNC长度</returns>
|
|||
private int GetMNCLength(string mcc) |
|||
{ |
|||
// 3位MNC的国家
|
|||
var threeDigitMNC = new[] |
|||
{ |
|||
"302", // 加拿大
|
|||
"310", // 美国
|
|||
"311", // 美国
|
|||
"312", // 美国
|
|||
"313", // 美国
|
|||
"314", // 美国
|
|||
"315", // 美国
|
|||
"316", // 美国
|
|||
"460", // 中国
|
|||
"466", // 台湾
|
|||
}; |
|||
|
|||
return threeDigitMNC.Contains(mcc) ? 3 : 2; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 验证MNC(移动网络代码)是否有效
|
|||
/// </summary>
|
|||
/// <param name="mnc">MNC代码</param>
|
|||
/// <returns>是否有效</returns>
|
|||
private bool IsValidMNC(string mnc) |
|||
{ |
|||
// MNC必须是2-3位数字
|
|||
return mnc.Length >= 2 && mnc.Length <= 3 && mnc.All(char.IsDigit); |
|||
} |
|||
} |
@ -0,0 +1,150 @@ |
|||
using CellularManagement.Domain.Common.Attributes; |
|||
using CellularManagement.Domain.ValueObjects; |
|||
using CellularManagement.Domain.Models; |
|||
|
|||
namespace CellularManagement.Domain.Common.Attributes; |
|||
|
|||
/// <summary>
|
|||
/// IMSI验证测试类
|
|||
/// </summary>
|
|||
public static class IMSIValidationTests |
|||
{ |
|||
/// <summary>
|
|||
/// 测试IMSI验证特性
|
|||
/// </summary>
|
|||
public static void TestIMSIValidationAttribute() |
|||
{ |
|||
var validationAttribute = new IMSIValidationAttribute(); |
|||
|
|||
// 测试有效的IMSI
|
|||
var validIMSIs = new[] |
|||
{ |
|||
"460001234567890", // 中国移动
|
|||
"460011234567890", // 中国联通
|
|||
"460021234567890", // 中国电信
|
|||
"466001234567890", // 台湾
|
|||
"310001234567890", // 美国
|
|||
"234001234567890", // 英国
|
|||
"262001234567890", // 德国
|
|||
}; |
|||
|
|||
foreach (var imsi in validIMSIs) |
|||
{ |
|||
var isValid = validationAttribute.IsValid(imsi); |
|||
Console.WriteLine($"IMSI {imsi}: {(isValid ? "有效" : "无效")}"); |
|||
} |
|||
|
|||
// 测试无效的IMSI
|
|||
var invalidIMSIs = new[] |
|||
{ |
|||
"", // 空字符串
|
|||
"123", // 太短
|
|||
"1234567890123456", // 太长
|
|||
"12345678901234a", // 包含字母
|
|||
"12345678901234!", // 包含特殊字符
|
|||
"999001234567890", // 无效MCC
|
|||
}; |
|||
|
|||
foreach (var imsi in invalidIMSIs) |
|||
{ |
|||
var isValid = validationAttribute.IsValid(imsi); |
|||
Console.WriteLine($"IMSI {imsi}: {(isValid ? "有效" : "无效")}"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 测试IMSI值对象
|
|||
/// </summary>
|
|||
public static void TestIMSIValueObject() |
|||
{ |
|||
// 测试有效的IMSI
|
|||
try |
|||
{ |
|||
var imsi = IMSI.Create("460001234567890"); |
|||
Console.WriteLine($"成功创建IMSI: {imsi}"); |
|||
Console.WriteLine($"MCC: {imsi.GetMCC()}"); |
|||
Console.WriteLine($"MNC: {imsi.GetMNC()}"); |
|||
Console.WriteLine($"MSIN: {imsi.GetMSIN()}"); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine($"创建IMSI失败: {ex.Message}"); |
|||
} |
|||
|
|||
// 测试无效的IMSI
|
|||
var invalidIMSIs = new[] |
|||
{ |
|||
"", |
|||
"123", |
|||
"1234567890123456", |
|||
"12345678901234a", |
|||
"999001234567890", |
|||
}; |
|||
|
|||
foreach (var imsiString in invalidIMSIs) |
|||
{ |
|||
try |
|||
{ |
|||
var imsi = IMSI.Create(imsiString); |
|||
Console.WriteLine($"意外成功创建IMSI: {imsi}"); |
|||
} |
|||
catch (ArgumentException ex) |
|||
{ |
|||
Console.WriteLine($"预期失败创建IMSI {imsiString}: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 测试UserInfo模型
|
|||
/// </summary>
|
|||
public static void TestUserInfoModel() |
|||
{ |
|||
// 测试有效的UserInfo
|
|||
try |
|||
{ |
|||
var userInfo = new UserInfo |
|||
{ |
|||
UserId = 1, |
|||
IMSI1 = "460001234567890", |
|||
IMSI2 = "460001234567891" |
|||
}; |
|||
Console.WriteLine($"成功创建UserInfo: UserId={userInfo.UserId}, IMSI1={userInfo.IMSI1}, IMSI2={userInfo.IMSI2}"); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine($"创建UserInfo失败: {ex.Message}"); |
|||
} |
|||
|
|||
// 测试无效的UserInfo
|
|||
try |
|||
{ |
|||
var userInfo = new UserInfo |
|||
{ |
|||
UserId = 1, |
|||
IMSI1 = "123", // 无效IMSI
|
|||
IMSI2 = "460001234567891" |
|||
}; |
|||
Console.WriteLine($"意外成功创建UserInfo: {userInfo}"); |
|||
} |
|||
catch (ArgumentException ex) |
|||
{ |
|||
Console.WriteLine($"预期失败创建UserInfo: {ex.Message}"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 运行所有测试
|
|||
/// </summary>
|
|||
public static void RunAllTests() |
|||
{ |
|||
Console.WriteLine("=== IMSI验证特性测试 ==="); |
|||
TestIMSIValidationAttribute(); |
|||
|
|||
Console.WriteLine("\n=== IMSI值对象测试 ==="); |
|||
TestIMSIValueObject(); |
|||
|
|||
Console.WriteLine("\n=== UserInfo模型测试 ==="); |
|||
TestUserInfoModel(); |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using CellularManagement.Domain.Common.Attributes; |
|||
using CellularManagement.Domain.ValueObjects; |
|||
|
|||
namespace CellularManagement.Domain.Models; |
|||
|
|||
/// <summary>
|
|||
/// 用户信息模型
|
|||
/// </summary>
|
|||
public class UserInfo |
|||
{ |
|||
/// <summary>
|
|||
/// 用户ID(1-5)
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "用户ID不能为空")] |
|||
[Range(1, 5, ErrorMessage = "用户ID必须在1到5之间")] |
|||
public int UserId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// IMSI1(国际移动用户识别码1)
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "IMSI1不能为空")] |
|||
public string IMSI1 { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// IMSI2(国际移动用户识别码2)
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "IMSI2不能为空")] |
|||
public string IMSI2 { get; set; } = null!; |
|||
} |
@ -0,0 +1,42 @@ |
|||
namespace CellularManagement.Domain.Services; |
|||
|
|||
/// <summary>
|
|||
/// IMSI验证服务接口
|
|||
/// </summary>
|
|||
public interface IIMSIValidationService |
|||
{ |
|||
/// <summary>
|
|||
/// 验证IMSI格式
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>验证结果</returns>
|
|||
(bool IsValid, string ErrorMessage) ValidateIMSI(string imsi); |
|||
|
|||
/// <summary>
|
|||
/// 验证IMSI列表
|
|||
/// </summary>
|
|||
/// <param name="imsiList">IMSI列表</param>
|
|||
/// <returns>验证结果</returns>
|
|||
(bool IsValid, List<string> ErrorMessages) ValidateIMSIs(IEnumerable<string> imsiList); |
|||
|
|||
/// <summary>
|
|||
/// 检查IMSI是否重复
|
|||
/// </summary>
|
|||
/// <param name="imsiList">IMSI列表</param>
|
|||
/// <returns>是否有重复</returns>
|
|||
(bool HasDuplicates, List<string> DuplicateIMSIs) CheckDuplicateIMSIs(IEnumerable<string> imsiList); |
|||
|
|||
/// <summary>
|
|||
/// 获取IMSI的国家信息
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>国家信息</returns>
|
|||
string GetCountryInfo(string imsi); |
|||
|
|||
/// <summary>
|
|||
/// 获取IMSI的运营商信息
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>运营商信息</returns>
|
|||
string GetOperatorInfo(string imsi); |
|||
} |
@ -0,0 +1,172 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using CellularManagement.Domain.Common.Attributes; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace CellularManagement.Domain.ValueObjects; |
|||
|
|||
/// <summary>
|
|||
/// IMSI(国际移动用户识别码)值对象
|
|||
/// </summary>
|
|||
public class IMSI |
|||
{ |
|||
private IMSI() { } |
|||
|
|||
/// <summary>
|
|||
/// IMSI值
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "IMSI不能为空")] |
|||
[IMSIValidation(ErrorMessage = "IMSI必须是15位数字,且符合IMSI格式要求")] |
|||
public string Value { get; private set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 创建IMSI
|
|||
/// </summary>
|
|||
/// <param name="value">IMSI值</param>
|
|||
/// <returns>IMSI实例</returns>
|
|||
public static IMSI Create(string value) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(value)) |
|||
{ |
|||
throw new ArgumentException("IMSI不能为空", nameof(value)); |
|||
} |
|||
|
|||
if (value.Length != 15) |
|||
{ |
|||
throw new ArgumentException("IMSI必须是15位数字", nameof(value)); |
|||
} |
|||
|
|||
if (!value.All(char.IsDigit)) |
|||
{ |
|||
throw new ArgumentException("IMSI只能包含数字", nameof(value)); |
|||
} |
|||
|
|||
// 使用验证特性进行验证
|
|||
var validationAttribute = new IMSIValidationAttribute(); |
|||
if (!validationAttribute.IsValid(value)) |
|||
{ |
|||
throw new ArgumentException(validationAttribute.FormatErrorMessage("IMSI"), nameof(value)); |
|||
} |
|||
|
|||
return new IMSI { Value = value }; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MCC(移动国家代码)
|
|||
/// </summary>
|
|||
/// <returns>MCC代码</returns>
|
|||
public string GetMCC() |
|||
{ |
|||
return Value.Substring(0, 3); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MNC(移动网络代码)
|
|||
/// </summary>
|
|||
/// <returns>MNC代码</returns>
|
|||
public string GetMNC() |
|||
{ |
|||
var mcc = GetMCC(); |
|||
var mncLength = GetMNCLength(mcc); |
|||
return Value.Substring(3, mncLength); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MSIN(移动用户识别号码)
|
|||
/// </summary>
|
|||
/// <returns>MSIN代码</returns>
|
|||
public string GetMSIN() |
|||
{ |
|||
var mcc = GetMCC(); |
|||
var mncLength = GetMNCLength(mcc); |
|||
return Value.Substring(3 + mncLength); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MNC长度
|
|||
/// </summary>
|
|||
/// <param name="mcc">MCC代码</param>
|
|||
/// <returns>MNC长度</returns>
|
|||
private int GetMNCLength(string mcc) |
|||
{ |
|||
// 3位MNC的国家
|
|||
var threeDigitMNC = new[] |
|||
{ |
|||
"302", // 加拿大
|
|||
"310", // 美国
|
|||
"311", // 美国
|
|||
"312", // 美国
|
|||
"313", // 美国
|
|||
"314", // 美国
|
|||
"315", // 美国
|
|||
"316", // 美国
|
|||
"460", // 中国
|
|||
"466", // 台湾
|
|||
}; |
|||
|
|||
return threeDigitMNC.Contains(mcc) ? 3 : 2; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 转换为字符串
|
|||
/// </summary>
|
|||
/// <returns>IMSI字符串</returns>
|
|||
public override string ToString() |
|||
{ |
|||
return Value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 相等性比较
|
|||
/// </summary>
|
|||
/// <param name="obj">比较对象</param>
|
|||
/// <returns>是否相等</returns>
|
|||
public override bool Equals(object? obj) |
|||
{ |
|||
if (obj is IMSI other) |
|||
{ |
|||
return Value == other.Value; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取哈希码
|
|||
/// </summary>
|
|||
/// <returns>哈希码</returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return Value.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 相等运算符
|
|||
/// </summary>
|
|||
/// <param name="left">左操作数</param>
|
|||
/// <param name="right">右操作数</param>
|
|||
/// <returns>是否相等</returns>
|
|||
public static bool operator ==(IMSI? left, IMSI? right) |
|||
{ |
|||
return EqualityComparer<IMSI>.Default.Equals(left, right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 不等运算符
|
|||
/// </summary>
|
|||
/// <param name="left">左操作数</param>
|
|||
/// <param name="right">右操作数</param>
|
|||
/// <returns>是否不等</returns>
|
|||
public static bool operator !=(IMSI? left, IMSI? right) |
|||
{ |
|||
return !(left == right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 隐式转换为字符串
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI实例</param>
|
|||
public static implicit operator string(IMSI imsi) |
|||
{ |
|||
return imsi.Value; |
|||
} |
|||
} |
@ -0,0 +1,364 @@ |
|||
using CellularManagement.Domain.Services; |
|||
using CellularManagement.Domain.Common.Attributes; |
|||
|
|||
namespace CellularManagement.Infrastructure.Services.Security; |
|||
|
|||
/// <summary>
|
|||
/// IMSI验证服务实现
|
|||
/// </summary>
|
|||
public class IMSIValidationService : IIMSIValidationService |
|||
{ |
|||
private readonly IMSIValidationAttribute _validationAttribute; |
|||
|
|||
public IMSIValidationService() |
|||
{ |
|||
_validationAttribute = new IMSIValidationAttribute(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 验证IMSI格式
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>验证结果</returns>
|
|||
public (bool IsValid, string ErrorMessage) ValidateIMSI(string imsi) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(imsi)) |
|||
{ |
|||
return (false, "IMSI不能为空"); |
|||
} |
|||
|
|||
if (imsi.Length != 15) |
|||
{ |
|||
return (false, "IMSI必须是15位数字"); |
|||
} |
|||
|
|||
if (!imsi.All(char.IsDigit)) |
|||
{ |
|||
return (false, "IMSI只能包含数字"); |
|||
} |
|||
|
|||
if (!_validationAttribute.IsValid(imsi)) |
|||
{ |
|||
return (false, _validationAttribute.FormatErrorMessage("IMSI")); |
|||
} |
|||
|
|||
return (true, string.Empty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 验证IMSI列表
|
|||
/// </summary>
|
|||
/// <param name="imsiList">IMSI列表</param>
|
|||
/// <returns>验证结果</returns>
|
|||
public (bool IsValid, List<string> ErrorMessages) ValidateIMSIs(IEnumerable<string> imsiList) |
|||
{ |
|||
var errorMessages = new List<string>(); |
|||
var isValid = true; |
|||
|
|||
foreach (var imsi in imsiList) |
|||
{ |
|||
var (isValidIMSI, errorMessage) = ValidateIMSI(imsi); |
|||
if (!isValidIMSI) |
|||
{ |
|||
isValid = false; |
|||
errorMessages.Add($"IMSI {imsi}: {errorMessage}"); |
|||
} |
|||
} |
|||
|
|||
return (isValid, errorMessages); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查IMSI是否重复
|
|||
/// </summary>
|
|||
/// <param name="imsiList">IMSI列表</param>
|
|||
/// <returns>是否有重复</returns>
|
|||
public (bool HasDuplicates, List<string> DuplicateIMSIs) CheckDuplicateIMSIs(IEnumerable<string> imsiList) |
|||
{ |
|||
var duplicateIMSIs = imsiList |
|||
.GroupBy(x => x) |
|||
.Where(g => g.Count() > 1) |
|||
.Select(g => g.Key) |
|||
.ToList(); |
|||
|
|||
return (duplicateIMSIs.Any(), duplicateIMSIs); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取IMSI的国家信息
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>国家信息</returns>
|
|||
public string GetCountryInfo(string imsi) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(imsi) || imsi.Length < 3) |
|||
{ |
|||
return "未知"; |
|||
} |
|||
|
|||
var mcc = imsi.Substring(0, 3); |
|||
return mcc switch |
|||
{ |
|||
"460" => "中国", |
|||
"466" => "台湾", |
|||
"455" => "澳门", |
|||
"454" => "香港", |
|||
"310" or "311" or "312" or "313" or "314" or "315" or "316" => "美国", |
|||
"234" or "235" => "英国", |
|||
"238" => "丹麦", |
|||
"240" => "瑞典", |
|||
"242" => "挪威", |
|||
"244" => "芬兰", |
|||
"246" => "立陶宛", |
|||
"247" => "拉脱维亚", |
|||
"248" => "爱沙尼亚", |
|||
"250" => "俄罗斯", |
|||
"255" => "乌克兰", |
|||
"257" => "白俄罗斯", |
|||
"259" => "摩尔多瓦", |
|||
"260" => "波兰", |
|||
"262" => "德国", |
|||
"268" => "葡萄牙", |
|||
"270" => "卢森堡", |
|||
"272" => "爱尔兰", |
|||
"274" => "冰岛", |
|||
"276" => "阿尔巴尼亚", |
|||
"278" => "马耳他", |
|||
"280" => "塞浦路斯", |
|||
"282" => "格鲁吉亚", |
|||
"283" => "亚美尼亚", |
|||
"284" => "保加利亚", |
|||
"286" => "土耳其", |
|||
"288" => "法罗群岛", |
|||
"290" => "格陵兰", |
|||
"292" => "安道尔", |
|||
"293" => "斯洛文尼亚", |
|||
"294" => "北马其顿", |
|||
"295" => "列支敦士登", |
|||
"297" => "黑山", |
|||
"302" => "加拿大", |
|||
"334" => "墨西哥", |
|||
"338" => "牙买加", |
|||
"340" => "瓜德罗普", |
|||
"342" => "巴巴多斯", |
|||
"344" => "安提瓜和巴布达", |
|||
"346" => "开曼群岛", |
|||
"348" => "英属维尔京群岛", |
|||
"350" => "百慕大", |
|||
"352" => "格林纳达", |
|||
"354" => "蒙特塞拉特", |
|||
"356" => "圣基茨和尼维斯", |
|||
"358" => "圣卢西亚", |
|||
"360" => "圣文森特和格林纳丁斯", |
|||
"362" => "荷属安的列斯", |
|||
"363" => "阿鲁巴", |
|||
"364" => "巴哈马", |
|||
"365" => "安圭拉", |
|||
"366" => "多米尼克", |
|||
"368" => "古巴", |
|||
"370" => "多米尼加共和国", |
|||
"372" => "海地", |
|||
"374" => "特立尼达和多巴哥", |
|||
"376" => "特克斯和凯科斯群岛", |
|||
"400" => "阿塞拜疆", |
|||
"401" => "哈萨克斯坦", |
|||
"402" => "不丹", |
|||
"404" or "405" or "406" => "印度", |
|||
"410" => "巴基斯坦", |
|||
"412" => "阿富汗", |
|||
"413" => "斯里兰卡", |
|||
"414" => "缅甸", |
|||
"415" => "黎巴嫩", |
|||
"416" => "约旦", |
|||
"417" => "叙利亚", |
|||
"418" => "伊拉克", |
|||
"419" => "科威特", |
|||
"420" => "沙特阿拉伯", |
|||
"421" => "也门", |
|||
"422" => "阿曼", |
|||
"424" => "阿联酋", |
|||
"425" => "以色列", |
|||
"426" => "巴林", |
|||
"427" => "卡塔尔", |
|||
"428" => "蒙古", |
|||
"429" => "尼泊尔", |
|||
"430" or "431" => "阿联酋", |
|||
"432" => "伊朗", |
|||
"434" => "乌兹别克斯坦", |
|||
"436" => "塔吉克斯坦", |
|||
"437" => "吉尔吉斯斯坦", |
|||
"438" => "土库曼斯坦", |
|||
"440" or "441" => "日本", |
|||
"450" => "韩国", |
|||
"452" => "越南", |
|||
"456" => "柬埔寨", |
|||
"457" => "老挝", |
|||
"467" => "朝鲜", |
|||
"470" => "孟加拉国", |
|||
"472" => "马尔代夫", |
|||
"502" => "马来西亚", |
|||
"505" => "澳大利亚", |
|||
"510" => "印度尼西亚", |
|||
"514" => "东帝汶", |
|||
"515" => "菲律宾", |
|||
"520" => "泰国", |
|||
"525" => "新加坡", |
|||
"528" => "文莱", |
|||
"530" => "新西兰", |
|||
"534" => "北马里亚纳群岛", |
|||
"535" => "关岛", |
|||
"536" => "瑙鲁", |
|||
"537" => "巴布亚新几内亚", |
|||
"539" => "汤加", |
|||
"540" => "所罗门群岛", |
|||
"541" => "瓦努阿图", |
|||
"542" => "斐济", |
|||
"543" => "瓦利斯和富图纳", |
|||
"544" => "美属萨摩亚", |
|||
"545" => "基里巴斯", |
|||
"546" => "新喀里多尼亚", |
|||
"547" => "法属波利尼西亚", |
|||
"548" => "库克群岛", |
|||
"549" => "萨摩亚", |
|||
"550" => "密克罗尼西亚联邦", |
|||
"552" => "帕劳", |
|||
"553" => "图瓦卢", |
|||
"554" => "托克劳", |
|||
"555" => "纽埃", |
|||
"602" => "埃及", |
|||
"603" => "阿尔及利亚", |
|||
"604" => "摩洛哥", |
|||
"605" => "突尼斯", |
|||
"606" => "利比亚", |
|||
"607" => "冈比亚", |
|||
"608" => "塞内加尔", |
|||
"609" => "毛里塔尼亚", |
|||
"610" => "马里", |
|||
"611" => "几内亚", |
|||
"612" => "科特迪瓦", |
|||
"613" => "布基纳法索", |
|||
"614" => "尼日尔", |
|||
"615" => "多哥", |
|||
"616" => "贝宁", |
|||
"617" => "毛里求斯", |
|||
"618" => "利比里亚", |
|||
"619" => "塞拉利昂", |
|||
"620" => "加纳", |
|||
"621" => "尼日利亚", |
|||
"622" => "乍得", |
|||
"623" => "中非共和国", |
|||
"624" => "喀麦隆", |
|||
"625" => "佛得角", |
|||
"626" => "圣多美和普林西比", |
|||
"627" => "赤道几内亚", |
|||
"628" => "加蓬", |
|||
"629" => "刚果共和国", |
|||
"630" => "刚果民主共和国", |
|||
"631" => "安哥拉", |
|||
"632" => "几内亚比绍", |
|||
"633" => "塞舌尔", |
|||
"634" => "苏丹", |
|||
"635" => "卢旺达", |
|||
"636" => "埃塞俄比亚", |
|||
"637" => "索马里", |
|||
"638" => "吉布提", |
|||
"639" => "肯尼亚", |
|||
"640" => "坦桑尼亚", |
|||
"641" => "乌干达", |
|||
"642" => "布隆迪", |
|||
"643" => "莫桑比克", |
|||
"645" => "赞比亚", |
|||
"646" => "马达加斯加", |
|||
"647" => "留尼汪", |
|||
"648" => "津巴布韦", |
|||
"649" => "纳米比亚", |
|||
"650" => "马拉维", |
|||
"651" => "莱索托", |
|||
"652" => "博茨瓦纳", |
|||
"653" => "斯威士兰", |
|||
"654" => "科摩罗", |
|||
"655" => "南非", |
|||
"657" => "厄立特里亚", |
|||
"659" => "南苏丹", |
|||
"702" => "伯利兹", |
|||
"704" => "危地马拉", |
|||
"706" => "萨尔瓦多", |
|||
"708" => "洪都拉斯", |
|||
"710" => "尼加拉瓜", |
|||
"712" => "哥斯达黎加", |
|||
"714" => "巴拿马", |
|||
"716" => "秘鲁", |
|||
"722" => "阿根廷", |
|||
"724" => "巴西", |
|||
"730" => "智利", |
|||
"732" => "哥伦比亚", |
|||
"734" => "委内瑞拉", |
|||
"736" => "玻利维亚", |
|||
"738" => "圭亚那", |
|||
"740" => "厄瓜多尔", |
|||
"742" => "法属圭亚那", |
|||
"744" => "巴拉圭", |
|||
"746" => "苏里南", |
|||
"748" => "乌拉圭", |
|||
"750" => "福克兰群岛", |
|||
_ => "未知" |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取IMSI的运营商信息
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>运营商信息</returns>
|
|||
public string GetOperatorInfo(string imsi) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(imsi) || imsi.Length < 5) |
|||
{ |
|||
return "未知"; |
|||
} |
|||
|
|||
var mcc = imsi.Substring(0, 3); |
|||
var mnc = GetMNC(imsi); |
|||
|
|||
// 这里可以根据MCC和MNC的组合来识别具体的运营商
|
|||
// 由于运营商信息较多,这里只提供一些常见的示例
|
|||
return $"{GetCountryInfo(imsi)} - MCC:{mcc}, MNC:{mnc}"; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MNC(移动网络代码)
|
|||
/// </summary>
|
|||
/// <param name="imsi">IMSI字符串</param>
|
|||
/// <returns>MNC代码</returns>
|
|||
private string GetMNC(string imsi) |
|||
{ |
|||
var mcc = imsi.Substring(0, 3); |
|||
var mncLength = GetMNCLength(mcc); |
|||
return imsi.Substring(3, mncLength); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取MNC长度
|
|||
/// </summary>
|
|||
/// <param name="mcc">MCC代码</param>
|
|||
/// <returns>MNC长度</returns>
|
|||
private int GetMNCLength(string mcc) |
|||
{ |
|||
// 3位MNC的国家
|
|||
var threeDigitMNC = new[] |
|||
{ |
|||
"302", // 加拿大
|
|||
"310", // 美国
|
|||
"311", // 美国
|
|||
"312", // 美国
|
|||
"313", // 美国
|
|||
"314", // 美国
|
|||
"315", // 美国
|
|||
"316", // 美国
|
|||
"460", // 中国
|
|||
"466", // 台湾
|
|||
}; |
|||
|
|||
return threeDigitMNC.Contains(mcc) ? 3 : 2; |
|||
} |
|||
} |
Loading…
Reference in new issue