对于独立开发者和小型软件公司,如何保护自己的知识产权、防止软件被恶意传播,成为了一个急需解决的技术难题。
今天,我将手把手教你用C#构建一套完整的软件授权验证系统,让你的软件拥有"身份证",有效防止盗版传播!
我们的方案核心思路是:通过获取计算机硬件信息生成唯一机器码,结合密钥生成授权码,实现软件与特定机器的绑定。
C#using System;
using System.Management;
using System.Security.Cryptography;
using System.Text;
using System.Linq;
namespace AppLicenseWinform
{
public static class LicenseHelper
{
/// <summary>
/// 获取硬盘序列号 - 相对稳定的硬件标识
/// </summary>
public static string GetDiskSerialNumber()
{
try
{
string serialNumber = "";
// 查询所有硬盘驱动器
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject disk in searcher.Get())
{
serialNumber = disk["SerialNumber"]?.ToString().Trim();
if (!string.IsNullOrEmpty(serialNumber))
break; // 获取到第一个有效序列号就退出
}
return serialNumber ?? "";
}
catch
{
return ""; // 异常时返回空字符串,确保程序不会崩溃
}
}
/// <summary>
/// 获取CPU序列号 - 最稳定的硬件标识
/// </summary>
public static string GetCpuId()
{
try
{
string cpuId = "";
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_Processor");
foreach (ManagementObject cpu in searcher.Get())
{
cpuId = cpu["ProcessorId"]?.ToString().Trim();
if (!string.IsNullOrEmpty(cpuId))
break;
}
return cpuId ?? "";
}
catch
{
return "";
}
}
/// <summary>
/// 生成机器码 - 将多个硬件信息组合并加密
/// </summary>
public static string GenerateMachineCode()
{
string cpu = GetCpuId();
string disk = GetDiskSerialNumber();
string raw = cpu + "-" + disk; // 组合CPU和硬盘信息
return GetMD5(raw); // MD5加密,生成32位十六进制字符串
}
/// <summary>
/// 生成授权码 - 基于机器码和密钥生成
/// </summary>
public static string GenerateLicense(string machineCode, string secret = "MySecretKey")
{
// 将机器码和密钥组合后进行MD5加密
return GetMD5(machineCode + secret);
}
/// <summary>
/// 验证授权码 - 检查用户输入的授权码是否有效
/// </summary>
public static bool ValidateLicense(string inputLicense, string secret = "MySecretKey")
{
string machineCode = GenerateMachineCode(); // 重新获取当前机器码
string expectedLicense = GenerateLicense(machineCode, secret); // 生成期望的授权码
// 忽略大小写比较
return expectedLicense.Equals(inputLicense, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// MD5加密辅助方法
/// </summary>
private static string GetMD5(string input)
{
using (var md5 = MD5.Create())
{
var data = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
// 将字节数组转换为大写十六进制字符串
return string.Concat(data.Select(b => b.ToString("X2")));
}
}
}
}
C#namespace AppLicenseWinform
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// 程序启动时自动显示机器码
txtMachineCode.Text = LicenseHelper.GenerateMachineCode();
}
/// <summary>
/// 验证授权按钮点击事件
/// </summary>
private void btnValidate_Click(object sender, EventArgs e)
{
string inputLicense = txtLicense.Text.Trim();
// 输入验证
if (string.IsNullOrEmpty(inputLicense))
{
lblResult.Text = "请输入授权码!";
lblResult.ForeColor = System.Drawing.Color.Orange;
return;
}
// 验证授权码
bool valid = LicenseHelper.ValidateLicense(inputLicense);
if (valid)
{
lblResult.Text = "✅ 授权成功,可以使用本软件!";
lblResult.ForeColor = System.Drawing.Color.Green;
// 这里可以启用软件的完整功能
EnableFullFeatures();
}
else
{
lblResult.Text = "❌ 授权无效,请联系开发者获取正确授权码。";
lblResult.ForeColor = System.Drawing.Color.Red;
}
}
/// <summary>
/// 生成授权码按钮(开发者测试用)
/// 实际发布时应该移除此功能,或者只在开发者模式下可用
/// </summary>
private void btnAuthorizationCode_Click(object sender, EventArgs e)
{
txtLicense.Text = LicenseHelper.GenerateLicense(txtMachineCode.Text);
}
/// <summary>
/// 启用软件完整功能
/// </summary>
private void EnableFullFeatures()
{
// 在这里添加授权成功后要执行的代码
// 比如:启用被禁用的菜单项、按钮等
}
}
}
坑点1:硬件更换导致授权失效
C#// 解决方案:可以考虑使用多个硬件信息的组合,允许部分变化
public static string GenerateMachineCodeFlexible()
{
var hardwareInfo = new List<string>
{
GetCpuId(),
GetDiskSerialNumber(),
GetMotherboardSerial(), // 主板序列号
GetMemorySerial() // 内存序列号
};
// 只要有3个以上匹配就认为是同一台机器
return GetMD5(string.Join("-", hardwareInfo.OrderBy(x => x)));
}
坑点2:获取硬件信息失败
C#// 解决方案:添加备用方案
public static string GetMachineFingerprint()
{
try
{
// 优先使用硬件信息
return GenerateMachineCode();
}
catch
{
// 备用方案:使用用户名+计算机名
return GetMD5(Environment.UserName + Environment.MachineName);
}
}
动态密钥
C#// 根据日期生成动态密钥,增加破解难度
private static string GetDynamicSecret()
{
var baseSecret = "MySecretKey";
var datePart = DateTime.Now.ToString("yyyyMM");
return GetMD5(baseSecret + datePart);
}
授权码有效期
C#public static string GenerateLicenseWithExpiry(string machineCode, DateTime expiry)
{
var expiryString = expiry.ToString("yyyyMMdd");
return GetMD5(machineCode + expiryString + "MySecretKey");
}
防调试检测
C#public static bool IsDebuggerAttached()
{
return System.Diagnostics.Debugger.IsAttached;
}
这套授权系统不仅能有效防止软件盗版,还具有良好的用户体验和开发维护性。你可以根据实际需求调整安全级别和功能特性。
💬 互动时间
你在开发中是否遇到过软件授权的需求?或者对这套方案有什么改进建议?欢迎在评论区分享你的经验和想法!
觉得这篇文章有用的话,请转发给更多需要的同行朋友! 🚀
关注我,获取更多C#实战技巧和项目经验分享!
相关信息
通过网盘分享的文件:AppLicenseWinform.zip 链接: https://pan.baidu.com/s/1jEH7rozjuEm38TVo9gd35Q?pwd=gf68 提取码: gf68 --来自百度网盘超级会员v9的分享
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!