.NET C/S架构软件用户授权设计方案(mac地址+白名单用户)|C/S开发框架
.NET C/S架构软件用户授权设计方案(mac地址+白名单用户)
设计目的
我们发布软件产品后要能限制用户使用权限,如:软件过期,发布试用版软件给用户使用。
案例开发环境
设计方案
设计白名单表 - sys_ClientWhitelist
CREATE TABLE [dbo].[sys_ClientWhitelist]
(
[isid] [varchar](50) NOT NULL,
[MAC] [varchar](50) NULL,
[ExpireTime] [datetime] NULL,
[FlagUse] [varchar](1) NULL,
[Remark] [varchar](200) NULL,
[CreationTime] [datetime] NULL,
[CreatedBy] [varchar](50) NULL
)
字段说明
- isid:记录主键
- MAC:mac地址
- ExpireTime:软件过期时间
- FlagUse:是否启用,Y:启用,N:不启用
- Remark:备注
- CreationTime:记录创建时间
- CreatedBy:创建人
软件授权接口设计 - IUserLicenseProvider
为了扩展其他授权策略,我们使用接口解耦。
/// <summary>
/// 软件授权接口
/// </summary>
public interface IUserLicenseProvider
{
/// <summary>
/// 检查软件授权,没有授权则抛出异常
/// </summary>
void Check();
/// <summary>
/// 软件是否过期,True:过期,False:没过期
/// </summary>
/// <returns></returns>
bool IsExpired();
/// <summary>
/// 软件授权信息,校验结果信息
/// </summary>
UserLicenseInfo LicenseInfo { get; }
}
用户授权校验结果类 - UserLicenseInfo
/// <summary>
/// 用户授权校验结果
/// </summary>
public class UserLicenseInfo
{
/// <summary>
/// 校验的Mac地址
/// </summary>
public string ValidMacAddress { get; set; }
/// <summary>
/// 软件过期日期
/// </summary>
public DateTime ExpireTime { get; set; }
/// <summary>
/// 软件是否过期
/// </summary>
public bool IsExpired { get; set; }
/// <summary>
/// 软件剩余天数
/// </summary>
public double DaysRemaining { get; set; }
/// <summary>
/// 校验结果信息
/// </summary>
public string ValidateResult { get; set; }
}
实现策略:mac地址+白名单用户 - MacBlacklistProvider
类定义为 internal(仅dll内部使用)
/// <summary>
/// Mac地址+白名单用户,授权策略
/// </summary>
internal class MacBlacklistProvider : IUserLicenseProvider
{
//授权的用户列表
internal static List<sys_ClientWhiteList> _Cache = null;
private UserLicenseInfo _LicenseInfo = null;
public UserLicenseInfo LicenseInfo
{
get { return _LicenseInfo; }
}
/// <summary>
/// 检查用户授权是否过期
/// </summary>
/// <exception cref="BizException"></exception>
public void Check()
{
if (IsExpired())
{
throw new BizException(_LicenseInfo.ValidateResult);
}
}
/// <summary>
/// 检查用户授权是否过期。
/// </summary>
/// <returns>true:软件已过期,false:没有过期</returns>
/// <exception cref="BizException"></exception>
public bool IsExpired()
{
this.LoadCache(true);
_LicenseInfo = new UserLicenseInfo
{
IsExpired = false,
ValidateResult = "软件使用正常,感谢您的支持!",
};
//获取电脑的mac地址
var mac = NetTools.GetMacByNetworkInterface().Where(w => !string.IsNullOrEmpty(w))
.Select(s => s.ToUpper()).Distinct().ToList();
sys_ClientWhiteList row = null;
//一台电脑有多个mac地址
if (mac != null && mac.Count > 0)
{
row = _Cache.Where(w => mac.Contains(w.MAC) && w.FlagUse == "Y").FirstOrDefault();
if (row == null)
{
_LicenseInfo.IsExpired = true;
_LicenseInfo.ValidateResult = "您没有授权使用本软件,请联系供应商!";
}
else
{
_LicenseInfo.IsExpired = row.ServerTime > row.ExpireTime;//判断软件过期:服务器日期>软件过期日期
_LicenseInfo.DaysRemaining = (row.ExpireTime.Value - row.ServerTime.Value).TotalDays;
_LicenseInfo.ExpireTime = row.ExpireTime.Value;
_LicenseInfo.ValidMacAddress = row.MAC;
if (_LicenseInfo.IsExpired)
{
_LicenseInfo.ValidateResult = "软件已过期,请联系供应商!";
}
}
}
return _LicenseInfo.IsExpired;
}
/// <summary>
/// 加载授权数据(mac+白名单)
/// </summary>
/// <param name="refreshData">是否刷新缓存数据</param>
private void LoadCache(bool refreshData = true)
{
if (refreshData || _Cache == null || _Cache.Count == 0)
{
_Cache = new bllUser().GetClientWhitelist();
//84-97-F6-89-E8-A0 => 去掉横杆
_Cache.ForEach(i => i.MAC = i.MAC.Replace("-", "").Trim().ToUpper());
}
}
}
DAL层,获取软件用户白名单列表
/// <summary>
/// DAL层获取软件用户白名单列表
/// </summary>
/// <returns></returns>
public List<sys_ClientWhiteList> GetClientWhitelist()
{
//仅获取启用的记录(FlagUse == "Y")
var list = _Database.GetQueryable<sys_ClientWhiteList>().Where(w => w.FlagUse == "Y").ToList();
var time = _Database.GetServerTime();
list.ForEach(i => i.ServerTime = time);
return list;
}
获取本地mac地址
参考:C#网络工具类NetTools,获取IP/MAC地址
https://www.cscode.net/archive/newdoc/254824675938309.html
用户软件授权提供者 - UserLicenseProvider
/// <summary>
/// 用户软件授权提供者
/// </summary>
public static class UserLicenseProvider
{
static IUserLicenseProvider _Stratage = null;
/// <summary>
/// 用户授权校验策略,单例模式
/// </summary>
public static IUserLicenseProvider Current
{
get
{
if (_Stratage == null) _Stratage = new MacBlacklistProvider();
return _Stratage;
}
}
}
使用方法
CSFrameworkV6旗舰版开发框架
if (BridgeFactory.InitializeBridge())//初始化后台数据连接
{
//检查软件授权
UserLicenseProvider.Current.Check();
//省略其他代码
}
其他软件
//初始化后台数据连接
//省略代码............
//检查软件授权
UserLicenseProvider.Current.Check();
测试报告
Test Case1
测试电脑的mac地址:00-E0-4C-44-17-F4
测试结果:没有软件登记、软件授权
Test Case2
测试电脑的mac地址:00-E0-4C-44-17-F4
启用:FlagUse=Y
过期时间:2024-11-24(当前时间:2024-11-25)
测试结果:软件已过期
Test Case3
测试电脑的mac地址:00-E0-4C-44-17-F4
过期时间:2024-11-26(当前时间:2024-11-25)
不启用:FlagUse=N
测试结果:您没有授权使用本软件,请联系供应商!
Test Case4
测试电脑的mac地址:00-E0-4C-44-17-F4
过期时间:2024-11-29(当前时间:2024-11-25)
不启用:FlagUse=Y
测试结果:软件运行正常,剩余使用天数:3
扫一扫加作者微信