首页 > 非C风格编程语言 > Asp.Net编程技术 > .NET 控件的许可验证方案
2010
10-28

.NET 控件的许可验证方案

作者:李双华

下载源代码

内容摘要: 本文描述了.NET控件的许可验证方案,并提供几种方案供读者参考。

读者对象: 熟悉C#语言 ,熟悉.NET技术

关键字:许可,控件,.NET技术

  伴随着.net开发技术的成熟,软件开发进入控件化时代。越来越多的公司投入软件开发领域,企图控制软件产业链的上游:提供解决方案。其中一部分公司就是提供控件。控件对外就象是一个黑盒子,借助于方法,属性和事件,开发人员即可轻易的开发出专业的应用程序, 
与此同时,软件的保护方法也不断出现。在共享软件时代,软件开发人员开发好程序,然后设计一个序列号生成算法,对正式许可的用户发布序列号,生成注册文件。在应用程序启动时检查注册文件,如果有则继续运行,否则中止运行或是提供部分功能。 
  .net 技术的出现,也提供了相应的软件保护解决方案。本文详细讨论.net 技术的软件保护方案与实现。我们可以采用各种方式来生产许可,授权用户使用我们开发的控件。常见的方式如下:

  1. 注册表。在控件安装时,在注册表中写入相应的键值,在控件运行时,查找该键,如找不到则抛出异常;
  2. 许可文件。在控件运行时,查找许可文件,如找不到,则抛出异常;
  3. 远程Web服务验证。在控件运行时,连接到远程的许可验证服务器,如能找到值,则表示已经授权;

  注册表的验证方式实现起来容易,但是也很容易发生验证异常。如果用户装有注册表监控程序,跟踪对注册表的每一项改动,则会很容易定位到键值,进而分析和利用,此外,这种方式对XCOPY也有影响,不方便部署应用程序;许可文件根据用户的硬件信息,比如硬盘序列号,或是MAC地址,邮件,生成一个许可文件,放在控件可以找到的地方,在运行时找到该许可文件,如果找不到,则阻止控件的运行;远程Web服务需用客户端能联网,在控件运行时向服务器发出查询许可的命令,如果找不到,则停止运行;如果用户不联网,这种方式有局限性,用户根本不能在脱机的情况下尝试运行该控件。

需要理解的对象:LicenseProvider

  MSDN中的解释是:提供 abstract 基类以便实现许可证提供程序。从 LicenseProvider 继承时,必须重写 GetLicense 方法。我们可以理解为一个许可证的提供程序,在控件需要验证时,提供许可授权,如果不提供许可,则不能使用该控件,抛出异常。这是个抽象类,不允许实例化,我们从该类派生,并且重写GetLicense方法。

      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;
              }
          }
      }      

  通过覆盖GetLicense方法,我们获取需要验证的控件的类型信息,然后在当前应用程序目录下查找以控件的lic文件,如找到,颁发许可,否则返回null值。 

License

  MSDN中的解释为:为所有许可证提供 abstract 基类。向控件的特定实例授予许可证。通俗的理解就是许可,给控件颁发的许可,表示控件已经授权过了,可以被使用。下面的代码可以帮助您理解许可的含义。

      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()
          {

          }
      }      

FileLicense会应用到控件上,如果返回给控件的FileLicense为空,则控件会抛出异常。 

应用许可提供程序

开发一个控件,如何应用许可验证呢?

如下代码所示,我们开发一个MyControl的控件,同时给它加上LicenseProvider特性(attribute),这样在该控件运行时,会用FileLicenseProvider来实行许可验证。

[LicenseProvider(typeof(FileLicenseProvider))]
public class MyControl : WebControl

此外,我们还需要在控件的构造方法中进一步调用验证方式:

      public MyControl()
      {
          try
          {
              license =  LicenseManager.Validate(typeof(MyControl), this);
          }
          catch
   				{
               HttpContext.Current.Response.Write("MyControl控件未授权,请联系程序开发商");
          }
      }

  如果该控件获取正确的授权,则会继续运行,否则因得不到许可而不能继续生成。 LicenseManager类会找到FileLicenseProvider类的GetLicense方法,来获取许可,经过各种验证方式(注册表,许可文件)来提供许可实例,如果验证失败,则会抛出LicenseException,表示无法找到许可。

许可验证服务器

  在注册表验证方式中,我们需要在控件的安装程序中嵌入脚本,在注册表中写入相应的键值;在本地许可文件验证方式下,我们需要根据序列号生产相应的许可文件;在远程Web服务的验证方式下,我们还需要设计一个远程的验证服务器,接受客户端的验证请求。 下面我们来讨论一下如何设计这个服务器应用程序。 
  Web服务是跨平台的通用协议,借助于SOAP(简单对象访问协议),我们能接受各种平台的验证请求。 
借助于ASP.NET Web服务,我们可以轻易的实现这个服务器端应用。 打开Visual Studio 2008,新建ASP.NET Web Service Application


图一 新建Web Service

把新建的服务名称改LicenseService.asmx,然后在该服务中提供验证方法

      [WebMethod]
      public bool  ValidateLicense(string mac)
      {
	  bool  ret = Validate(mac);
	  return  ret;
      }

Validate方法会去查找数据库记录,返回结果,提供给客户端。 为此,我们还需要设计数据库。


图二 SQL设计视图

  这里,我们采用验证客户端MAC地址的方式,如果能找到该地址,则把Enabled设为1,否则找不到,表示该MAC地址未授权,返回false给许可验证提供程序。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]

应用程序

由于开发的是Web控件,我们设计一个Web站点,来测试我们的控件保护方案。右击解决方案,添加现有站点(Web site)


图三 添加现有站点

把我们的控件从工具栏中拖动到一个Web页面中,生成应用程序,然后F5,调试运行。页面的源代码如下:

 <uc:MyControl ID="MyControl1" runat="server" />

另外,在Web.config中添加如下代码,您可以不必在每一个页面中都加入控件引用。

  <pages>
  <controls>
        <add tagPrefix="uc" namespace="HTSystem"  assembly="HTSystem.Component,
        Version=1.1.0.0, Culture=neutral,  PublicKeyToken=c2c8c99b69b1086e"/>
        </controls>
  </pages>  		

您可能也注意到了,我们给自己写的组件MyControl添加了版本和强命名元数据,这样可以保护我们的组件。 

总结

  本文试图给您提供几种常用的许可验证的方式。文中详细讨论了许可文件的验证方案,分析了如何借助Web服务技术,设计远程验证服务器,另外,您还应该了解注册表的方式的验证方式。 您可以通过阅读源代码,详细了解这三种方式的实现。

源:http://www.vckbase.com/document/viewdoc/?id=1892


留下一个回复