首页 > C风格编程语言 > C#编程资料 > .NET 控件的许可验证方案
2010
01-26

.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/code/viewcode.asp?id=3219coolker2010-01-26 00:25:27


.NET 控件的许可验证方案》有 0 条评论

  1. coolker 说:

    作者:李双华

    下载源代码

    内容摘要: 本文描述了.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

    http://www.vckbase.com/document/journal/vckbase55/images/aspnetlicimg1.JPG','Image‘);” onmouseover=”this.style.cursor=’hand’” onmouseout=”this.style.cursor=”” src=”http://www.vckbase.com/document/journal/vckbase55/images/aspnetlicimg1.JPG” height=”440″ width=”683″ border=”0″ />
    图一 新建Web Service

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

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

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

    http://www.vckbase.com/document/journal/vckbase55/images/aspnetlicimg2.JPG','Image‘);” onmouseover=”this.style.cursor=’hand’” onmouseout=”this.style.cursor=”” src=”http://www.vckbase.com/document/journal/vckbase55/images/aspnetlicimg2.JPG” height=”58″ width=”339″ border=”0″ />
    图二 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)

    http://www.vckbase.com/document/journal/vckbase55/images/aspnetlicimg3.JPG','Image‘);” onmouseover=”this.style.cursor=’hand’” onmouseout=”this.style.cursor=”” src=”http://www.vckbase.com/document/journal/vckbase55/images/aspnetlicimg3.JPG” height=”455″ width=”578″ border=”0″ />
    图三 添加现有站点

    把我们的控件从工具栏中拖动到一个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/code/viewcode.asp?id=3219coolker2010-01-26 00:25:27

留下一个回复