World! "/>
p>
form>
body>
html>
To see if the authorization is taken effect, remove the licenseDControls.licensedLabel.lic file or move it to another. Regenerate the application or make changes that can cause the application to restart. The role of this step is to clear the license cache managed by the license provider specified in the metadata of the LicensedLabel control. Request the licensedlabeltest.aspx page in the browser. This page will generate errors shown in the figure below.
Figure 1. LicensedLabeltest.aspx page Attempts to generate errors when using LicensedLabel without effective licenses
Back to top
.NET framework authorization structure
The following figure (Fig. 2) illustrates the authorization structure of the .NET framework. It can be seen from which a page attempts to instantiate the LicensedLabel control described in front section. Although the actual steps occur in the context of the server control, the figure shows the key steps that make up the .NET framework authorization structure, and any runtime authorization scheme. The exact step performed by the license provider is a specific authorization scheme specific to the provider implementation. For example, as described in the ASP.NET Server Control Authorization Infrastructure in this article, the licensed cache function shown in the figure is ServerLicenseProvider. The class displayed in bold is the .NET framework class, which is a derived class that is implemented in a berth.
Figure 2. Authorized structure of .NET framework
The main steps for implementing authorization to control include:
1. The authorized control is called in its constructor system.comPonentModel.licenseManager.validate. (This control can also call the static method LicenseManager.issalid in its constructor. In this case, the return type is different from the figure, and it will not cause an exception.)
2.LicenseManager.validate method Check the metadata of the component, obtain the type of license provider from the license provider attribute applied to the component. The license provider class must be derived from the System.comPonentmodel.licenseProvider class.
3.LicenseManager is instantiated for the license provider class (the type specified in the System.ComponentModel.LicenseProvideRAttribute metadata property) is instantiated, and the type of the component is passed to the license provider and indicates that the component is still in design or Running.
4. The license provider finds the license for the component in the license cache. If you find a license, the license provider verifies the license. Note that the license cache lookup and licensed storage are not general requirements, but a SERVERLICENSEPROVIDER-we have implemented license provider.
a. (for the first time) The license provider obtains license data and verifies. If the data is invalid, the license provider will trigger the system.componentmodel.licenseException exception.
b. (for the first time) If the license data is valid, the license provider will create a license (from system.componentmodel.license derived). In addition, the license provider also verifies the license, and if the license is valid, store it in the license cache. 5. The license provider returns a valid license to the license manager or triggered license exceptions.
6.LicenseManager.validate method Returns a valid license or pass the license anomaly to the call code.
7. If the LicenseManager returns a valid license, the constructor will initialize the class, which will be instantiated. Otherwise, the constructor passes the licenseException to an attempt to instantiate the code. The error message displayed in the graph in the authorized control drill section is generated by the ASP.NET runtime, and the ASP.NET runtime processing When a page is used in the case where the authorized control is used without payment, it is used by the control. Conformationally functional permission is abnormal.
The initial creation refers to the first instantiation of the component in the web application. If another instance of the component is created on the same page or on another page in the application (in the same request or in later requests), steps 4a and 4b do not occur. For performance, ServerLicenseProvider caches per apps (instead of pressing per page or each session) each application.
The design of the authorized structure in the .NET framework makes illegal use components (but not impossible). If the user tries to use a licensed component without permission, the authorization mechanism will make it clear that the component is being illegally used. Authorization does not generate tamper evidence.
The authorization structure in the .NET frame is provided by the following four classes in the System.ComponentModel namespace:
• LicenseManager: This class is responsible for instantiating the license provider specified in the metadata of the component. The license manager also passes the type and authorization context to the license provider, and the authorization context indicates that the component is used in design or running at runtime. In addition to calling the Validate or IsValid method of the LicenseManager class in the component's constructor, you don't have to know other details about LicenseManager. • LicenseProviderattribute: This property specifies the type of license provider responsible for creating and verifying component licenses. You must apply this property to support authorized components. • LicenseProvider: This class contains the core features of any authorization scheme - the task of issuing and verifying the license. To implement authorization support, you must create a custom license provider by derived from LicenseProvider, and implement the abstract method of the base class GetLicense to provide authorization logic. The implementation of the license provider ServerLicenseProvider will be discussed in this section. • License: This class is the software abstraction of license data (such as license data contained in the .lic file). To implement licensing classes, you must derive from the License class and achieve the abstract properties of the base class LicenseKey. In the next section of this article, we will implement a license class that is used with ServerLicenseProvider.
The .NET Framework provides the default implementation of the license provider in the System.comPonentModel.licfilelicenseProvider class. The license provider relies on a visual designer (such as Visual Studio .NET) to obtain authorization data during design and compilation, the license data is used as a resource to embed the program of the application using the licensed component. The LICFileLicenseProvider class can be used by the Windows Form Control, but it does not meet the ASP.NET Server Control Requirements for the ASP.NET Server Control Requirements in this article. Back to top
ASP.NET Server Control Authorization Infrastructure
This section describes the core authorization implementation, which provides specific deployment of the ASP.NET Server Control Program. This implementation is included in two classes, ServerLicenseProvider and ServerLicense, which derived from the LicenseProvider and the license class. We hope that in future ASP.NET versions, there is a built-in authorization support in a similar set of base classes. You can use and extend the ServerLicenseProvider and ServerLicense classes, without having to check their source code, just like you are using the class in the .NET framework. However, for the integrity, this section includes these classes of the code.
ServerLicenseProvider class
The ServerLicenseProvider class is derived from LicenseProvider, which covers the GetLicense method to implement the core server control authorization requirements. ServerLicenseProvider meets the server authorization requirements previously described above - do not compile models, runtime authorization support, authorization caches, and Xcopy deployment. ServerLicenseProvider will implement the default authorization scheme that loads license data from .lic text file, which is stored in a directory named licensees in the web application root directory. The structure in this directory is based on the name and version of the assembly displayed in the authorized control drill section in this article. The default solution relies on the following contents in the .lic file: " IS Licensed.".
// ServerLicenseProvider.cs
//
Using system;
Using system.collections;
Using system.collections.specialized;
Using system.componentmodel;
Using system.io;
Using system.diagnostics;
USING SYSTEM.GLOBALIZATION;
Using system.Web;
Namespace licensedControls {
Public Class ServerLicenseProvider: licenseProvider {
Private Static Readonly ServerLicenseCollector LicenseCollector =
New ServerLicenseCollector ();
Protected Virtual ServerLicense CreateLicense (Type Type, String
Key) {
Return New ServerLicense (Type, Key);
}
Protected Virtual ServerLicense CreateemptyLicense (Type Type) {
Return New ServerLicense (TYPE, STRING.EMPTY);
}
Public Override License GetLicense (LicenseContext Context, Type
Type, Object Instance, Bool AllowExceptions {ServerLicense License = NULL;
String ErrorMessage = NULL;
IF (context.usagemode == licenseusagemode.designtime) {
License = Createemptylicense (TYPE);
}
Else {
License = licenseCollector.getlicense (TYPE);
IF (license == NULL) {
String licensedata = getLicenSedata (TYPE);
IF ((licensedata! = null) && (licenseData.length! =
0)) {
IF (ValidateLicenseData (Type, licensedata) {
ServerLicense newLicense = CreateLicense (Type,
Licensedata);
IF (ValidateLicense (NewLicense, Out
ERRORMESSAGE)) {
License = NewLicense;
LicenseCollector.Addlicense (TYPE,
license;
}
}
}
}
Else {
ValidateLicense (license, out errorMessage) ==
False) {
License = NULL;
}
}
}
IF (allowexceptions && (license == null) {
IF (errorMessage == null) {
Throw new licenseException (TYPE);
}
Else {
Throw new licenseexception (Type, Instance,
ErrorMessage);
}
}
Return license;
}
Protected Virtual String GetLicenSedata (Type Type) {
String licensedata = NULL;
Stream licensestream = NULL;
Try {
Licensteream = getLicenSedataStream (Type);
IF (LicensStream! = null) {
StreamReader SR = New StreamReader (Licensteream);
Licensedata = Sr.Readline ();
}
}
Finally {
IF (LicensStream! = null) {
Licensteream.close ();
Licensteram = NULL;
}
}
Return licensedata;
}
Protected Virtual Stream getLicenseDataStream (Type Type) {
String assemblypart = type.assembly.getname (). Name
String VersionPart =
Type.assembly.getname (). Version.toString ();
String relativepath = "~ / licenses /" assemblypart "/"
VersionPart "/" Type.Fullname ".lic"; string licenseesfile = null;
Try {
Licensesfile =
HttpContext.current.server.mappath (RelativePath);
IF (file.exists (licensesfile) == false) {
Licensesfile = NULL;
}
}
Catch {
}
IF (licenseesfile! = null) {
Return New FileStream (licenssfile, Filemode.Open,
FileAccess.read, Fileshare.Read;
}
Return NULL;
}
Protected Virtual Bool ValidateLicense (ServerLicense License, Out
String ErrorMessage) {
ErrorMessage = NULL;
Return True;
}
Protected Virtual Bool ValidateLicensedata (Type Type, String
Licensedata) {
String licenseKey = Type.FullName "is licensed."
Return String.comPare (licenseKey, Licensedata, True,
CultureInfo.invariantculture) == 0;
}
Private Sealed Class ServerLicenseCollector {
Private idictionary _collectedLicense;
Public ServerLicenseCollector () {
_CollectedLicenses = new hybriddictionary ();
}
Public void addlicense (Type ObjectType, ServerLicense License)
{
IF (ObjectType == Null) {
Throw New Argumentnullexception ("ObjectType");
}
IF (license == NULL) {
Throw New Argumentnullexception ("ObjectType");
}
_COLLECTEDLICENSES [ObjectType] = license
}
Public ServerLicense getLicense (Type ObjectType) {
IF (ObjectType == Null) {
Throw New Argumentnullexception ("ObjectType");
}
IF (_COLLECTEDLICENS.COUNT == 0) {
Return NULL;
}
Return (ServerLicense) _CollectedLicenses [ObjectType];
}
Public void Removelense (Type ObjectType) {
IF (ObjectType == Null) {
Throw New Argumentnullexception ("ObjectType");
}
_CollectedLicenses.Remove (ObjectType);
}
}
}
}
ServerLicense class ServerLicense is a basis license class compatible with ServerLicenseProvider. ServerLicense is derived from the License class and implements abstract properties of the base class.
// ServerLicense.cs
//
Using system;
Using system.componentmodel;
Using system.diagnostics;
Namespace licensedControls {
Public Class ServerLicense: license {
Private type_type;
PRIVATE STRING_KEY;
Public ServerLicense (Type Type, String Key) {
_Type = Type;
_key = key;
}
Public override string licenseKey {
Get {
Return_Key;
}
}
Public type licensedtype {
Get {
Return_type;
}
}
Public override void dispose () {
}
}
}
Back to top
Extended default authorization program
ServerLicenseProvider and ServerLicense classes have implemented a simple default authorization program. You can extend these classes to implement your own custom license scheme with more complex verification logic. To implement a custom license, derive your own license provider from ServerLicenseProvider and override one or more virtual methods thereof (see below). To complete your authorization scheme, you may also implement license classes derived from ServerLicense and use with the license provider.
The following table describes the overlay methods defined in the ServerLicenseProvider class.
Overwn: Protected Virtual ServerLicense CreateLicense (Type Type, String Key) creates and returns a ServerLicense instance for the specified authorized type. This string parameter is the verified license data associated with the type. The derived license provider can overwrite this method to return to the derived license. For example, refer to the ExpiringLicenseProvider described in the expiration license schedule in this article. Protected Virtual ServerLicense Createemptylicense (Type Type) creates and returns an empty ServerLicense instance that is not associated with real license data. ServerLicenseProvider uses an empty license to support design. The derived license provider can overwrite this method to return empty derived license. Protected Virtual String GetLicenSedata (Type Type) Retrieves license data from the license flow by reading the first row of data in the license stream. The derived license provider can override this method to read from other licensed storage not based on streaming. Protected Virtual Stream GetLicenSedataStream (Type Type) Opens the stream used to read the license data. This method also includes logic of virtual paths that form to the appropriate .lic file. The derived license provider can overwrite this method to return a custom stream displayed in the EncryptedLicenseProvider example in the encrypted scheme of this article. Protected Virtual Bool ValidateLicense (ServerLicense License, Out String ErrorMessage) Verify the license for the cache. This verification occurs at each request permit. The derived license provider can overwrite this method to implement its own verification logic. The ExpiringLicenseProvider example described in this Incending Permission Scheme section implements an authorization scheme based on the use. Protected Virtual Bool ValidateLicensedata (Type Type, String Licensedata) Verify license data, create licenses if the data is valid, and return TRUE. The derived license provider can achieve custom verification rules by overwriting this method. Back to top
Expiration license
This section and the next section will explain how to extend the default authorization implementation provided to create a custom license program. The expired license scheme shown in this section will extend the default scheme by disabling the control after the control has been specified. This solution can be used for the demo version of the control.
The expiration license scheme is implemented in the ExpiringLicenseProvider class.
// ExpiringLicenseProvider.cs
//
Using system;
Using system.diagnostics;
USING SYSTEM.GLOBALIZATION;
Namespace licensedControls {
Public Class ExpiringLicenseProvider: ServerLicenseProvider {
Protected Override ServerLicense CreateLicense (Type Type, String
Key) {
String [] parts = key.split (';');
Debug.assert (Parts.length == 2);
Return New ExpiringLicense (Type, Key, Int32.parse (Parts [1],
CultureInfo.invariantculture);
}
Protected Override Bool ValidateLicense (ServerLicense License, Out
String ErrorMessage) {
ErrorMessage = NULL; ExpiringLicense Testlicense = (ExpiringLicense) license;
Testlicense.incrementusageCounter ();
IF (Testlicense.isexpired) {
ErrorMessage = "The license for"
Testlicense.licensedType.Name "HAS EXPIRED."
Return False;
}
Return True;
}
Protected Override Bool ValidateLicensedata (Type Type, String
Licensedata) {
String [] parts = licensedata.split (';');
IF (parts.length == 2) {
Return Base.ValidateLicensedata (Type, Parts [0]);
}
Else {
Return False;
}
}
}
}
The EXPIRINGENSEPROVIDER class is derived from ServerLicenseProvider, which covers the following methods of the base class:
• CREATEEMPTYLICENSE to create licenses associated with real license data. Empty license is suitable for use in design. • CREATELICENSE to create a license for the usage count with the .lic file specified. • ValidateLicense to check if the license has expired. ValidateLicense will count the increment using it before checking. • ValidateLicenSedata to check if the text string in the .lic file contains two parts separated by a semicolon: " IS licensed.;
The ExpiringLicenseProvider class uses the ExpiringLicense class as its license type.
// ExpiringLicense.cs
//
Using system;
Namespace licensedControls {
Public Class ExpiringLicense: ServerLicense {
Private Int_usagelimit;
Private int _usagecount;
Public ExpiringLicense (Type Type, String Key, int usagelimit):
Base (Type, Key) {
_USAGELIMIT = usagelimit;
}
Public Bool ISEXPIRED {
Get {
Return_usagecount> _usagelimit;
}
}
Public void incrementusageCounter () {
_USAGECUNT ;
}
}
}
The EXPIRINGLICENSE class implements the following logic:
• Define two private fields to store usage restrictions and use counts. • Public IncrementUSAGECUNTER method, the method is incremented by counting each time you access an ExpiringLicense object. • Open ISEXPIRED properties that determine if the license has expired by comparing using the counting limit.
Note that the count can be saved in the ExpiringLicense itself because the server license is cached. ServerLicenseProvider only creates an instance of a license for a specific component type and saves the license in its internal license cache. However, storage data is not very safe in the cached license object. For example, if the application is restarted, the use count will be reset to zero, thus makes the total use limit greater than the license specified in the license data. Similarly, if the application is deployed on the farm, the total usage count on all servers may exceed the expected usage limit. However, logic implemented in ExpiringLicense is acceptable because the purpose of authorization is to prevent unauthorized use of components in order to prevent unauthorized use of the component in order to achieve significant impact on the performance of the application. The following code shows controls that use the ExpiringLicenseProvider class for their authorization scheme.
// ExpiringLicensedLabel.cs
//
Using system;
Using system.componentmodel;
Using system.Web.ui.webcontrols;
Namespace licensedControls {
[
LicenseProvider (typeof (ExpiringLicenseProvider))
]
Public class expiringlicensedLabel: label {
Public expiringlicensedlabel () {
LicenseManager.validate (typeof (expiringlicensedlabel);
}
}
}
The contents of the.lic file in ExpiringLicenSedlabel are "licensedControls.exPiringLicensedLabel is licensed.; 5".
As shown above, if the license is specified in a plaintext file, the application developers can easily deceive the data in the file. You can increase the security of the license program by encrypting license data (as shown in the following section).
Back to top
Encrypted license scheme
This section expands the default scheme to implement a encrypted license provider that decrypts these encrypted license data when reading encrypted license data. The following code shows the EncryptedLicenseProvider class.
// EncryptedLicenseProvider.cs
//
Using system;
Using system.diagnostics;
Using system.io;
Using system.security.cryptography;
Namespace licensedControls {
Public Class EncryptedLicenseProvider: ServerLicenseProvider {
// this is a 64-bit key generated from the string
// "5fb281f6".
//
Private static readonly byte [] encryptionKeybytes =
New byte [] {0x35, 0x46, 0x42, 0x32, 0x38, 0x31, 0x46, 0x36};
Protected Override Stream GetLicenSedataStream (Type Type) {
Stream BaseStream = Base.GetLicensedataStream (TYPE);
IF (BaseStream == Null) {
Return NULL;
}
DescryptoServiceProvider DES = New DescryptoserviceProvider (); des.key = encryptionKeybytes;
DES.IV = EncryptionKeybytes;
Icryptotransform deSDecryptor = des.createdecryptor ();
Return New CryptostReam (BaseStream, Desdecryptor,
CryptostReammode.read;
}
}
}
The EncryptedLicenseProvider class is derived from ServerLicenseProvider and overwrites the getLicenSedataStream method, which creates a System.io.Stream object to read license data. EncryptedLicenseProvider is packaged with System.Security.cryptography.cryptostream to decrypt it when the license data is read. The CryptostReam used in the example uses a data encryption standard (DES) password algorithm with a 64-bit encryption key, and the encryption key is embedded in the EncryptedLicenseProvider class itself. The reason why it is allowed to be embedded in this way because the design of the authorization structure makes it difficult for damage permit, or even impossible. Win32 Security API provides more complex mechanisms for more storage encryption keys; however, those techniques are often not suitable for Xcopy deployment.
ServerLicense is ideal for licensed classes as EncryptedLicenseProvider, so there is no need to implement any derived license classes for this permit provider.
The EncryptedLicensedLabel control shown in the following code uses the license scheme implemented in the EncryptedLicenseProvider class.
// encryptedLicensedLabel.cs
//
Using system;
Using system.componentmodel;
Using system.Web.ui.webcontrols;
Namespace licensedControls {
[
LicenseProvider (IPRYPTEDLICENSEPROVIDER)
]
Public class encryptedLicensedLabel: label {
Public EncryptedLicenSedlabel () {
LicenseManager.validate (typeptedLicensedLabel);
}
}
}
The figure below shows the .lic file associated with EncryptedLicensedLabel.
Figure 3. Content of the licensedControls.EncryptedLicensedlabel file
The content of this file is encrypted using the same key embedded in EncryptedLicenseProvider. The data in this file is a string "licensedControls.encryptedLicensedLabel is licensed". However, people cannot read because they have been encrypted. The encryption tool EnclicactEn.exe and its source code EncryptedLicensegenerator.cs are provided in the sample files herein.
Encryption makes the authorization plan more powerful. For example, you can use encryption in an expiration scheme to improve its security. You can encrypt your own data and user's registration information, instead of encryption of fixed strings like this example.
Back to top
Authorization implementation checklist
The following table describes the tasks that need to be executed when implementing the authorization of the server control:
• Implement a license provider derived from the ServerLicenseProvider class and override one or more virtual methods of the base class to provide the logic of the authorization scheme. • Implement a license class that is derived from the ServerLicense class and uses the license provider you implemented (see the content after the previous item symbol). This step is not required if ServerLicense is available for your authorization scheme (as shown in the encryptedLicenseProvider example of this article). • Add authorization support to your component by applying the licenseProViderattribute metadata properties and delivering the type of license provider you implemented (see the first project symbol). There is also a need to call LicenseManager.validate from the constructor of the component. • Create authorization data for components. You can save this data in the .lic file or save any other forms required by the license scheme. • (Optional) Create a tool to generate license data. For example, encryption tool EnclicactGen.exe provided with the sample files of this article. If you want to create components for commercial distribution, you will find that you have a tool with an automatic creation license data is very useful. • If the license data of the component is included in the file (such as .lic file), provide the application developer's instructions to create the directory structure required for your license scheme, and copy the license file to the web application. The necessary position. Back to top
summary
This article discusses the requirements of the ASP.NET server control and the .NET framework authorization structure. We tell the three key elements - the license provider class that supports authorized code, license data, and authentication licenses - how to provide authorization functions. We offer a default ASP.NET server control authorization implementation, which creates a specific deployment of the server control authorization program, and we also explain how to extend this default authorization implementation by creating different custom licensing schemes.
Go to the original English page