.NET中的許可證機制
主要類:
System.ComponentModel.License(為所有許可證提供 abstract 基類。向組件的特定實例授予許可證)
System.ComponentModel.LicenseContext(指定何時可使用授權的對象,並且提供一種方法,用以獲取為支持在其域內運行的許可證所需要的附加服務)
System.ComponentModel.LicenseException(表示當組件不能被授予許可證時引發的異常。)
System.ComponentModel.LicenseManager(提供屬性和方法,用以將許可證添加到組件和管理 LicenseProvider)
System.ComponentModel.LicenseProvider(提供 abstract 基類以便實現許可證提供程序)
System.ComponentModel.LicenseProviderAttribute(指定要與類一起使用的 LicenseProvider)
許可證機制簡介
.Net Framework中的許可證驗證機制基於System.ComponentModel命名空間中的License、LicenseContext、LicenseException、LicenseManager、LicenseProvider和LicenseProviderAttribute六個類實現的。
License是一個抽象類,用於代表許可證主體;
LicenseContext中保存了許可證的上下文,其中UsageMode屬性可以用來獲取當前是運行時(runtime)還是設計模式(designtime);
LicenseException是許可證相關的異常,當許可證信息不可用時,在調用LicenseProvider(或其派生類)實例的GetLicense方法時將拋出此類型的異常;
LicenseManager是一個密封(sealed)類,LicenseManager提供了多個靜態(static)方法用於驗證許可證、獲取許可證等操作;
LicenseProviderAttribute屬性用於指定某一個類所采用的許可證提供程序(LicenseProvider)的具體類型;
LicenseProvider是一個抽象類,用於代表許可證驗證機制提供程序。LicenseProvider的類型通過LicenseProviderAttribute屬性提供給CLR,當調用LicenseManager的操作時,LicenseManager將根據LicenseProviderAttribute中所提供的LicenseProvider類型創建LicenseProvider實例,並進行相應操作。LicFileLicenseProvider基於文本文件的許可證機制。
簡單應用:
1:首先要創建一個License,但是因為License是抽象的,所以要創建一個集成自License的子類,實現License的一些方法。
2:創建一個LicenseProvider類,這個類要集成LicenseProvider的類。實現一些方法。LicenseProvider類提供了驗證機制的程序。LicenseProvider類要重載GetLicense(LicenseContext,Type ,object ,bool)方法,該方法真正提供了,一些算法,去實現驗證。
3:創建一個自定義的類,並且給該類添加LicenseProviderAttribute屬性。指定對這個類進行驗證的機制采用LiceseProvider。
具體代碼:
定義Licese類
private class MyLicense : License
{
private String mLicenseKey = null;
private MyLicenseProvider mProvider = null;
public MyLicense(MyLicenseProvider provider, String key)
{
this.mProvider = provider;
this.mLicenseKey = key;
}
public override string LicenseKey
{
get { return this.mLicenseKey; }
}
public override void Dispose()
{
this.mProvider = null;
this.mLicenseKey = null;
}
}
定義LicenseProvider類
[ReflectionPermission(SecurityAction.Deny, MemberAccess=false, ReflectionEmit=false)]
internal class MyLicenseProvider : LicenseProvider
{
構造函數
public MyLicenseProvider()
{ }
/// <summary>
/// 獲取本機MAC地址 其實這個不管是獲取本機硬件參數的任何信息都可以這要能標志該機器即可
/// </summary>
private String GetMacAddress()
{
String macAddr = null;
ManagementClass inetAdapter = new ManagementClass("WIN32_NetworkAdapterConfiguration");
ManagementObjectCollection objList = inetAdapter.GetInstances();
foreach (ManagementObject mobj in objList)
{
if ((bool)mobj["IPEnabled"])
{
macAddr = mobj["MacAddress"].ToString().Replace(":", "-");
break;
}
}
return macAddr;
}
/// <summary>
/// 獲取Assembly所在目錄 獲取應用程序所在的目錄
/// </summary>
private String GetAssemblyPath(LicenseContext context)
{
String fileName = null;
Type type = this.GetType();
ITypeResolutionService service = (ITypeResolutionService)context.GetService(typeof(ITypeResolutionService));
if (service != null)
{
fileName = service.GetPathOfAssembly(type.Assembly.GetName());
}
if (fileName == null)
{
fileName = type.Module.FullyQualifiedName;
}
return Path.GetDirectoryName(fileName);
}
private String Encrypt(String source) 加密算法,可以用,也可不用,這里為了更安全,就用。
{
/**
* 加密算法
*/
byte[] keyData = Encoding.ASCII.GetBytes("");
byte[] ivData = Encoding.ASCII.GetBytes("4iJ9Qw#L");
MemoryStream stream = new MemoryStream();
DES desProvider = new DESCryptoServiceProvider();
CryptoStream cs = new CryptoStream(stream,
desProvider.CreateEncryptor(keyData, ivData),
CryptoStreamMode.Write);
byte[] buffer = Encoding.ASCII.GetBytes(source);
cs.Write(buffer, 0, buffer.Length);
cs.FlushFinalBlock();
cs.Close();
buffer = stream.GetBuffer();
stream.Close();
return Convert.ToBase64String(buffer);
return source;
}
public override License GetLicense(LicenseContext context, Type type, object instance, bool allowExceptions)
{
MyLicense license = null;
// 計算MAC地址加密串
String macAddr = this.GetMacAddress();
String encrypt = this.Encrypt(macAddr);
if (context != null)
{
if (context.UsageMode == LicenseUsageMode.Runtime)
{
String savedLicenseKey = context.GetSavedLicenseKey(type, null);
if (encrypt.Equals(savedLicenseKey))
{
return new MyLicense(this, encrypt);
}
}
if (license != null)
{
return license;
}
// 打開License文件 'license.dat'
String path = this.GetAssemblyPath(context);
String licFile = Path.Combine(path, "license.dat");
if (File.Exists(licFile))
{
Stream fs = new FileStream(licFile, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
String readedLicenseKey = sr.ReadToEnd();
sr.Close();
fs.Close();
if (encrypt.Equals(readedLicenseKey))
{
license = new MyLicense(this, encrypt);
}
}
if (license != null)
{
context.SetSavedLicenseKey(type, encrypt);
}
}
if (license == null)
{
System.Windows.Forms.MessageBox.Show("!!!尚未注冊!!!");
return new MyLicense(this, "evaluate");
}
return license;
}
指定該類進行許可驗證的程序采用MyLicenseProvider 這句必須的。
[LicenseProvider(typeof(MyLicenseProvider))]
public partial class LicenseHelper
{
private License mLicense = null;
public LicenseHelper()
{
this.mLicense = LicenseManager.Validate(typeof( LicenseHelper), this);
}
~ LicenseHelper() 析構函數,在C#中,不常用。
{
if (this.mLicense != null)
{
this.mLicense.Dispose();
this.mLicense = null;
}
}
}
這樣。在程序中調用LicenseHelper是就要進行驗證,否則。就會出現異常。
該方法也可以對軟件進行加密,只是在GetLicense(LicenseContext, type, object,bool);方法中寫的機密算法要復雜一些。但是道理都是這樣的。
出處:http://blog.csdn.net/joyhen/article/details/22715223