为了创建有效的许可系统,您必须将其链接到用户计算机的一个或多个属性(MAC 地址、操作系统 ID、硬盘序列号、CPU 序列号等...)。
如果您不这样做,您只会发布可以从一个用户转移到另一个用户的许可证。如果一个用户决定将他的许可文件传播到世界各地,那么您注定要失败,因为每个人都可能会获取该许可文件并使用它来解锁您的应用程序。
但是,如果您将许可证文件链接到用户计算机的一个或多个属性,如上所述,您必须能够获得这些属性:
- 在用户决定购买您的应用程序之前;
- 当用户激活他的许可证时。
第一个场景
您将软件作为试用版发布。当它第一次启动时,您在注册表或隐藏在某处的文件中设置到期日期。您在应用程序启动时检查到期日期,一旦到期,您就会抛出错误,并且您不再让使用过的人与您的应用程序一起玩。
在应用程序中,您可以在某处创建一个Register Now 按钮。单击它时,应用程序检索机器属性并将它们传递到将打开的网页/表单以让用户执行付款。该页面将负责验证机器属性、接收付款,最后根据这些属性提供有效的许可证代码。
在应用程序中,您必须实现允许表单创建许可代码的相同逻辑,因为每次启动应用程序时您都需要使用它们来验证代码本身。一个伪代码示例:
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lc = GetLicenseCode();
if (~strcmp(sha1([mp1 mp2 mp3]),lc))
errordlg('Invalid license code!');
return;
end
这是最简单的路径。但请记住,如果用户机器的一个或多个属性发生变化(因为他更改了设备或重新安装了他的操作系统),他的许可证将失效,您必须提供处理这种情况的客户协助服务.
第二种情况
这个难度要大得多。您将无法提前知道用户的机器属性。因此,您的许可系统将分两步运行。当用户购买您的应用程序时,您会发布一个唯一代码(例如称为LID)。然后,一旦用户将其插入到您的应用程序中,您的应用程序必须将其与机器属性一起发送回。然后计算最终密钥(例如称为LKey)并将其发送回用户。
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lkey = GetLicenseKey();
if (~strcmp(sha1([mp1 mp2 mp3]),lkey))
errordlg('Invalid license code!');
return;
end
机器属性
第一个解决方案已通过注释提供给您:位于注册表项HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography 中的MachineGuid 值。它很结实。但它只适用于 Windows 机器。使用winqueryreg 访问注册表。
另一个不错的选择是Window Domain Controller Security ID,它是另一个特定于机器的唯一标识符。您可以在 Matlab 中使用Java 代码检索它:
wdc_sid = com.sun.security.auth.module.NTSystem.getDomainSID();
或通过 Windows 注册表项 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\GroupMembership。如果您想与旧的 Matlab 版本保持一定的向后兼容性,则应该使用注册表方法。不幸的是,Window Domain Controller Security ID 是另一个仅在 Windows 下运行的机器上可用的标识符。
如果您想让您的许可系统适应所有可能的操作系统和环境,您必须使用一种更通用的方法,该方法基于普遍可访问的硬件属性:MAC 地址、硬盘序列等。据我所知,最可靠的属性是MAC地址,因为它的唯一性,虽然没有被授予,但几乎可以肯定,而且更换网络适配器的频率非常低(实际上损坏硬盘的机会更多)。使用Java代码获取机器网卡的MAC地址,如下:
mac_addrs = '';
net_int = java.net.NetworkInterface.getNetworkInterfaces();
while (net_int.hasMoreElements)
mac_addr = net_int.nextElement.getHardwareAddress();
if (~isempty(mac_addr))
mac_addrs = [mac_addrs, '-', sprintf('%.2X',typecast(mac_addr,'uint8'))];
end
end
mac_addrs = mac_addrs(2:end);
上面的计算产生了一个字符数组,表示机器上找到的所有 MAC 地址的串联结果。同样,出于兼容性原因,这可能不适用于旧的 Matlab 版本,因此您必须使用更复杂的方法,如 here 所述。
[编辑]
这种基于底层操作系统检索 MAC 地址的方法可能更容易:
switch computer('arch')
case {'maci','maci64'}
[~,a]=system('ifconfig');
c=strfind(a,'en0');if ~isempty(c),a=a(c:end);end
c=strfind(a,'en1');if ~isempty(c),a=a(1:c-1);end
% find the mac address
b=strfind(a,'ether');
mac_add=a(1,b(1)+6:b(1)+22);
case {'win32','win64'}
[~,a]=system('getmac');b=strfind(a,'=');
mac_add=a(b(end)+1:b(end)+19);
case {'glnx86','glnxa64'}
[~,a]=system('ifconfig');b=strfind(a,'Ether');
mac_add=a(1,b(1)+17:b(1)+33);
otherwise,mac_add=[];
end
我在this article的cmets中找到了。