作者:李双华 内容摘要: 本文描述了.NET控件的许可验证方案,并提供几种方案供读者参考。 读者对象: 熟悉C#语言 ,熟悉.NET技术 关键字:许可,控件,.NET技术 伴随着.net开发技术的成熟,软件开发进入控件化时代。越来越多的公司投入软件开发领域,企图控制软件产业链的上游:提供解决方案。其中一部分公司就是提供控件。控件对外就象是一个黑盒子,借助于方法,属性和事件,开发人员即可轻易的开发出专业的应用程序, 注册表的验证方式实现起来容易,但是也很容易发生验证异常。如果用户装有注册表监控程序,跟踪对注册表的每一项改动,则会很容易定位到键值,进而分析和利用,此外,这种方式对XCOPY也有影响,不方便部署应用程序;许可文件根据用户的硬件信息,比如硬盘序列号,或是MAC地址,邮件,生成一个许可文件,放在控件可以找到的地方,在运行时找到该许可文件,如果找不到,则阻止控件的运行;远程Web服务需用客户端能联网,在控件运行时向服务器发出查询许可的命令,如果找不到,则停止运行;如果用户不联网,这种方式有局限性,用户根本不能在脱机的情况下尝试运行该控件。 需要理解的对象:LicenseProvider MSDN中的解释是:提供 abstract 基类以便实现许可证提供程序。从 LicenseProvider 继承时,必须重写 GetLicense 方法。我们可以理解为一个许可证的提供程序,在控件需要验证时,提供许可授权,如果不提供许可,则不能使用该控件,抛出异常。这是个抽象类,不允许实例化,我们从该类派生,并且重写GetLicense方法。 通过覆盖GetLicense方法,我们获取需要验证的控件的类型信息,然后在当前应用程序目录下查找以控件的lic文件,如找到,颁发许可,否则返回null值。 License MSDN中的解释为:为所有许可证提供 abstract 基类。向控件的特定实例授予许可证。通俗的理解就是许可,给控件颁发的许可,表示控件已经授权过了,可以被使用。下面的代码可以帮助您理解许可的含义。
FileLicense会应用到控件上,如果返回给控件的FileLicense为空,则控件会抛出异常。 应用许可提供程序
开发一个控件,如何应用许可验证呢? 如下代码所示,我们开发一个MyControl的控件,同时给它加上LicenseProvider特性(attribute),这样在该控件运行时,会用FileLicenseProvider来实行许可验证。 此外,我们还需要在控件的构造方法中进一步调用验证方式: 如果该控件获取正确的授权,则会继续运行,否则因得不到许可而不能继续生成。 LicenseManager类会找到FileLicenseProvider类的GetLicense方法,来获取许可,经过各种验证方式(注册表,许可文件)来提供许可实例,如果验证失败,则会抛出LicenseException,表示无法找到许可。
许可验证服务器 在注册表验证方式中,我们需要在控件的安装程序中嵌入脚本,在注册表中写入相应的键值;在本地许可文件验证方式下,我们需要根据序列号生产相应的许可文件;在远程Web服务的验证方式下,我们还需要设计一个远程的验证服务器,接受客户端的验证请求。 下面我们来讨论一下如何设计这个服务器应用程序。 把新建的服务名称改LicenseService.asmx,然后在该服务中提供验证方法 Validate方法会去查找数据库记录,返回结果,提供给客户端。 为此,我们还需要设计数据库。
这里,我们采用验证客户端MAC地址的方式,如果能找到该地址,则把Enabled设为1,否则找不到,表示该MAC地址未授权,返回false给许可验证提供程序。SQL 脚本如下: 应用程序
由于开发的是Web控件,我们设计一个Web站点,来测试我们的控件保护方案。右击解决方案,添加现有站点(Web site) 把我们的控件从工具栏中拖动到一个Web页面中,生成应用程序,然后F5,调试运行。页面的源代码如下: 另外,在Web.config中添加如下代码,您可以不必在每一个页面中都加入控件引用。 您可能也注意到了,我们给自己写的组件MyControl添加了版本和强命名元数据,这样可以保护我们的组件。 总结
本文试图给您提供几种常用的许可验证的方式。文中详细讨论了许可文件的验证方案,分析了如何借助Web服务技术,设计远程验证服务器,另外,您还应该了解注册表的方式的验证方式。 您可以通过阅读源代码,详细了解这三种方式的实现。
与此同时,软件的保护方法也不断出现。在共享软件时代,软件开发人员开发好程序,然后设计一个序列号生成算法,对正式许可的用户发布序列号,生成注册文件。在应用程序启动时检查注册文件,如果有则继续运行,否则中止运行或是提供部分功能。
.net 技术的出现,也提供了相应的软件保护解决方案。本文详细讨论.net 技术的软件保护方案与实现。我们可以采用各种方式来生产许可,授权用户使用我们开发的控件。常见的方式如下:
public class FileLicenseProvider : System.ComponentModel.LicenseProvider
{
public override License GetLicense(LicenseContext context, Type type, object instance, bool allowExceptions)
{
if (context.UsageMode == LicenseUsageMode.Designtime)
{
// 开发人员设计时不需要许可,直接颁发许可证
return new FileLicense(this, "The App");
}
else
{
string licenseFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, type.FullName+".lic");
if (File.Exists(licenseFile))
return new FileLicense(this, "The App");
else
return null;
}
}
}
public class FileLicense : System.ComponentModel.License
{
//许可验证提供程序
private FileLicenseProvider owner;
private string key;
public FileLicense(FileLicenseProvider owner, string key)
{
this.owner = owner;
this.key = key;
}
//许可Key,通俗的理解是序列号。
public override string LicenseKey
{
get
{
return key;
}
}
public override void Dispose()
{
}
}
[LicenseProvider(typeof(FileLicenseProvider))]
public class MyControl : WebControl
public MyControl()
{
try
{
license = LicenseManager.Validate(typeof(MyControl), this);
}
catch
{
HttpContext.Current.Response.Write("MyControl控件未授权,请联系程序开发商");
}
}
Web服务是跨平台的通用协议,借助于SOAP(简单对象访问协议),我们能接受各种平台的验证请求。
借助于ASP.NET Web服务,我们可以轻易的实现这个服务器端应用。 打开Visual Studio 2008,新建ASP.NET Web Service Application
图一 新建Web Service [WebMethod]
public bool ValidateLicense(string mac)
{
bool ret = Validate(mac);
return ret;
}
图二 SQL设计视图CREATE TABLE [dbo].[LicenseUser](
[MAC] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
[Enabled] [smallint] NULL,
CONSTRAINT [PK_LicenseUser] PRIMARY KEY CLUSTERED
(
[MAC] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
图三 添加现有站点 <uc:MyControl ID="MyControl1" runat="server" />
<pages>
<controls>
<add tagPrefix="uc" namespace="HTSystem" assembly="HTSystem.Component,
Version=1.1.0.0, Culture=neutral, PublicKeyToken=c2c8c99b69b1086e"/>
</controls>
</pages>
>> 本文固定链接: http://www.vcgood.com/archives/3440