ASP.NET Server Control Authorization

xiaoxiao2021-03-06  95

Release Date: 4/1/2004

| Update Date: 4/1/2004

Summary: Understand the authorization requirements for the ASP.NET server control, understand the ASP.NET control implementation available for .NET Framework version 1.0 and 1.1. This implementation can be extended to create a custom server-side authorization scheme. (23 page print pages)

Nikhil Kothari Microsoft ASP.NET Group

Vandana Datye Freelance

July 2003

Applicable to: Microsoft? ASP.NET

Please download AspnetControllicensing.msi.

background

This article assumes that the reader is familiar with the Microsoft? ASP.NET programming and the ASP.NET server control.

All rights. This part of the content is licensed by Microsoft Press. For more information about the book, see http://www.microsoft.com/mspress/books/5728.asp.

This page

Introduction ASP.NET Server Control Requirements Authorized Control Drive. Net Framework Authorized Structure ASP.NET Server Control Authorized Infrastructure Extension Default Authorization Program Expiral License Program Encryption Program Authorization Remindrical List Summary

Introduction

The Microsoft .NET framework has a built-in scalable authorization structure that supports all managed components (including business objects, Windows Form Controls, and ASP.NET Server Controls) to authorize and rule. This article is based on this structure to provide authorization implementations specifically for ASP.NET controls, and you can extend the authorization implementation to create custom licensing programs, such as:

• Simple Authorization Scheme - Only check whether there is a valid license data to determine if the control is enabled. • Permits expirations after each use of authorization scheme - after a use count. This solution can be used for the demo version of the control. After the license expires, the application developers can register (and purchase) your control and receive a not permission. • An ASP.NET server control is enabled only when requesting from a particular client (such as a local computer). This program can be used to implement the trial version of the control. • Rely on encryption to prevent application developers from performing license data spoofing.

Back to top

ASP.NET server control authorization requirements

ASP.NET Server Controls Authorization Program must meet the following requirements:

• Support for non-compilation schemes. ASP.NET web applications often use dynamic compilation models, so there is no set of precompiled assessments associated with the application. The authorization mechanism should not rely on the license as an assembly resource embedded in the program set. • Support runtime licenses. Page developers use a visual design tool and simple text editor to develop their own pages. The authorization mechanism cannot rely on design, and must provide runtime verification. Moreover, the runtime authorization implementation should not have dependencies with any (optional) design. • Support license caching mechanisms. Ideally, each application should only retrieve a license data instead of being retrieved for each page request, because the retrieval logic will involve a large overhead, for example, open the file and decrypt information. The license should be created when you need to permit, and a cache is made so that you will be reused on the server later. You can still authenticate the license for the cache when you use the license to implement the license based on the license. • Support XCOPY deployment. ASP.NET allows page developers to deploy their web applications by copying files between computers on the network. Authorization schemes should not rely on registry, or other-specific computed-based resources that are prohibited from deployment. For the sake of simplicity, we use the server control in the previous list. However, authorization requirements apply to all ASP.NET server components. Similarly, the ASP.NET control authorization scheme described herein also applies to other ASP.NET server components.

Back to top

Authorized control drill

Control authorization involves three key elements:

• Support for authorized code • License data • Check license data, issue licenses and certification licenses when using controls

Authorized server control

The LicensedLabel server control listed below is derived from the ASP.NET System.Web.ui.WebControls.label control and adds authorization support. The authorization function is provided with the code displayed in a bold.

// licensedlabel.cs

//

Using system;

Using system.componentmodel;

Using system.Web.ui.webcontrols;

Namespace licensedControls {

[

LicenseProvider (TypeOf (ServerLicenseProvider)

]

Public class licensedlabel: label {

Public licensedlabel () {

LicenseManager.validate (TypeOf (licensedLabel));

}

}

}

This example illustrates to support the authorization, you must add the following to the code of any server components:

• In the constructor's constructor, call the System.comPonentModel.LicenseManager class Validate, and transfer it as a parameter to the component's type. If the control does not have a valid license, the Validate method of the licenseManager will trigger System.comPonentModel.licenseException. Another method is that in the constructor, you can call the static method isvalid for the LicenseManager class, so it will not cause an exception. If you want to enable controls in the case where there is no valid license (so on the simple version), call the IsValid method. • Apply System.ComponentModel.licenseProVideRATITRIBUTE metadata properties to your component and deliver the type of license provider (from System.comPonentModel.licenseProvider). The ASP.NET Server Control Authorization Infrastructure section shows the implementation of the license provider ServerLicenseProvider for the licensedlabel control. As shown in Figure 1, changes you must do for controls for authorizations are minimal. The real authorization function is in the license provider class, and later describes this part.

If you have implemented licenses in the Windows Form Control, you may be surprisingly found that LicensedLabel does not leave its license. This is because LicensedLabel uses a license provider that caokes the license on the server.

License data

The license data provides information on authenticating and merging to the license by the authorization structure. You can provide license data in many different ways (such as expiration, counting or unique key). The type and location of license data is specified by a specific authorization scheme. License data is usually provided in the file that extension .lic. The license data of the LicensedLabel control in Figure 1 is located in a file called licensedControls.licensedLabel.lic, which contains only text "licensedControls.LicensedLabel is licensed".

Use the authorized control on the page

The ReadMe documentation provided as the code example of this article describes how to build these examples.

Use the licensedlabel control in the page

1. Copy the licensedControls assembly (including the licensedLabel control) to the application's / bin directory. This step is required if you use Microsoft Visual Studio .NET and add a reference to the licensedControls project in your web application project.

2. Copy the licenseDControls.licensedLabel.lic file to the application's licensees / licensedControls / 1.0.0.0 directory.

Now, you should use controls from any page in your application.

The following code shows a page that uses the LicensedLabel control.

<% @ Page language = "c #"%>

<% @ Register tagprefix = "lc" askSEMBLY = "licensedControls"

Namespace = "licensedControls"%>

licensedLabel Sample </ Title></p> <p></ hEAD></p> <p><body></p> <p><form method = "post" runat = "server" id = "form1"> <p></p> <p><lc: licensedlabel runat = "server" id = "text =" Hello "TEXT ="</p> <p>World! "/></p> <p></ p></p> <p></ form></p> <p></ body></p> <p></ html></p> <p>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.</p> <p>Figure 1. LicensedLabeltest.aspx page Attempts to generate errors when using LicensedLabel without effective licenses</p> <p>Back to top</p> <p>.NET framework authorization structure</p> <p>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.</p> <p>Figure 2. Authorized structure of .NET framework</p> <p>The main steps for implementing authorization to control include:</p> <p>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.)</p> <p>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.</p> <p>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.</p> <p>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.</p> <p>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.</p> <p>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.</p> <p>6.LicenseManager.validate method Returns a valid license or pass the license anomaly to the call code.</p> <p>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.</p> <p>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.</p> <p>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.</p> <p>The authorization structure in the .NET frame is provided by the following four classes in the System.ComponentModel namespace:</p> <p>• 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.</p> <p>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</p> <p>ASP.NET Server Control Authorization Infrastructure</p> <p>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.</p> <p>ServerLicenseProvider class</p> <p>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: "<Component's Complete Type> IS Licensed.".</p> <p>// ServerLicenseProvider.cs</p> <p>//</p> <p>Using system;</p> <p>Using system.collections;</p> <p>Using system.collections.specialized;</p> <p>Using system.componentmodel;</p> <p>Using system.io;</p> <p>Using system.diagnostics;</p> <p>USING SYSTEM.GLOBALIZATION;</p> <p>Using system.Web;</p> <p>Namespace licensedControls {</p> <p>Public Class ServerLicenseProvider: licenseProvider {</p> <p>Private Static Readonly ServerLicenseCollector LicenseCollector =</p> <p>New ServerLicenseCollector ();</p> <p>Protected Virtual ServerLicense CreateLicense (Type Type, String</p> <p>Key) {</p> <p>Return New ServerLicense (Type, Key);</p> <p>}</p> <p>Protected Virtual ServerLicense CreateemptyLicense (Type Type) {</p> <p>Return New ServerLicense (TYPE, STRING.EMPTY);</p> <p>}</p> <p>Public Override License GetLicense (LicenseContext Context, Type</p> <p>Type, Object Instance, Bool AllowExceptions {ServerLicense License = NULL;</p> <p>String ErrorMessage = NULL;</p> <p>IF (context.usagemode == licenseusagemode.designtime) {</p> <p>License = Createemptylicense (TYPE);</p> <p>}</p> <p>Else {</p> <p>License = licenseCollector.getlicense (TYPE);</p> <p>IF (license == NULL) {</p> <p>String licensedata = getLicenSedata (TYPE);</p> <p>IF ((licensedata! = null) && (licenseData.length! =</p> <p>0)) {</p> <p>IF (ValidateLicenseData (Type, licensedata) {</p> <p>ServerLicense newLicense = CreateLicense (Type,</p> <p>Licensedata);</p> <p>IF (ValidateLicense (NewLicense, Out</p> <p>ERRORMESSAGE)) {</p> <p>License = NewLicense;</p> <p>LicenseCollector.Addlicense (TYPE,</p> <p>license;</p> <p>}</p> <p>}</p> <p>}</p> <p>}</p> <p>Else {</p> <p>ValidateLicense (license, out errorMessage) ==</p> <p>False) {</p> <p>License = NULL;</p> <p>}</p> <p>}</p> <p>}</p> <p>IF (allowexceptions && (license == null) {</p> <p>IF (errorMessage == null) {</p> <p>Throw new licenseException (TYPE);</p> <p>}</p> <p>Else {</p> <p>Throw new licenseexception (Type, Instance,</p> <p>ErrorMessage);</p> <p>}</p> <p>}</p> <p>Return license;</p> <p>}</p> <p>Protected Virtual String GetLicenSedata (Type Type) {</p> <p>String licensedata = NULL;</p> <p>Stream licensestream = NULL;</p> <p>Try {</p> <p>Licensteream = getLicenSedataStream (Type);</p> <p>IF (LicensStream! = null) {</p> <p>StreamReader SR = New StreamReader (Licensteream);</p> <p>Licensedata = Sr.Readline ();</p> <p>}</p> <p>}</p> <p>Finally {</p> <p>IF (LicensStream! = null) {</p> <p>Licensteream.close ();</p> <p>Licensteram = NULL;</p> <p>}</p> <p>}</p> <p>Return licensedata;</p> <p>}</p> <p>Protected Virtual Stream getLicenseDataStream (Type Type) {</p> <p>String assemblypart = type.assembly.getname (). Name</p> <p>String VersionPart =</p> <p>Type.assembly.getname (). Version.toString ();</p> <p>String relativepath = "~ / licenses /" assemblypart "/" </p> <p>VersionPart "/" Type.Fullname ".lic"; string licenseesfile = null;</p> <p>Try {</p> <p>Licensesfile =</p> <p>HttpContext.current.server.mappath (RelativePath);</p> <p>IF (file.exists (licensesfile) == false) {</p> <p>Licensesfile = NULL;</p> <p>}</p> <p>}</p> <p>Catch {</p> <p>}</p> <p>IF (licenseesfile! = null) {</p> <p>Return New FileStream (licenssfile, Filemode.Open,</p> <p>FileAccess.read, Fileshare.Read;</p> <p>}</p> <p>Return NULL;</p> <p>}</p> <p>Protected Virtual Bool ValidateLicense (ServerLicense License, Out</p> <p>String ErrorMessage) {</p> <p>ErrorMessage = NULL;</p> <p>Return True;</p> <p>}</p> <p>Protected Virtual Bool ValidateLicensedata (Type Type, String</p> <p>Licensedata) {</p> <p>String licenseKey = Type.FullName "is licensed."</p> <p>Return String.comPare (licenseKey, Licensedata, True,</p> <p>CultureInfo.invariantculture) == 0;</p> <p>}</p> <p>Private Sealed Class ServerLicenseCollector {</p> <p>Private idictionary _collectedLicense;</p> <p>Public ServerLicenseCollector () {</p> <p>_CollectedLicenses = new hybriddictionary ();</p> <p>}</p> <p>Public void addlicense (Type ObjectType, ServerLicense License)</p> <p>{</p> <p>IF (ObjectType == Null) {</p> <p>Throw New Argumentnullexception ("ObjectType");</p> <p>}</p> <p>IF (license == NULL) {</p> <p>Throw New Argumentnullexception ("ObjectType");</p> <p>}</p> <p>_COLLECTEDLICENSES [ObjectType] = license</p> <p>}</p> <p>Public ServerLicense getLicense (Type ObjectType) {</p> <p>IF (ObjectType == Null) {</p> <p>Throw New Argumentnullexception ("ObjectType");</p> <p>}</p> <p>IF (_COLLECTEDLICENS.COUNT == 0) {</p> <p>Return NULL;</p> <p>}</p> <p>Return (ServerLicense) _CollectedLicenses [ObjectType];</p> <p>}</p> <p>Public void Removelense (Type ObjectType) {</p> <p>IF (ObjectType == Null) {</p> <p>Throw New Argumentnullexception ("ObjectType");</p> <p>}</p> <p>_CollectedLicenses.Remove (ObjectType);</p> <p>}</p> <p>}</p> <p>}</p> <p>}</p> <p>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.</p> <p>// ServerLicense.cs</p> <p>//</p> <p>Using system;</p> <p>Using system.componentmodel;</p> <p>Using system.diagnostics;</p> <p>Namespace licensedControls {</p> <p>Public Class ServerLicense: license {</p> <p>Private type_type;</p> <p>PRIVATE STRING_KEY;</p> <p>Public ServerLicense (Type Type, String Key) {</p> <p>_Type = Type;</p> <p>_key = key;</p> <p>}</p> <p>Public override string licenseKey {</p> <p>Get {</p> <p>Return_Key;</p> <p>}</p> <p>}</p> <p>Public type licensedtype {</p> <p>Get {</p> <p>Return_type;</p> <p>}</p> <p>}</p> <p>Public override void dispose () {</p> <p>}</p> <p>}</p> <p>}</p> <p>Back to top</p> <p>Extended default authorization program</p> <p>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.</p> <p>The following table describes the overlay methods defined in the ServerLicenseProvider class.</p> <p>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</p> <p>Expiration license</p> <p>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.</p> <p>The expiration license scheme is implemented in the ExpiringLicenseProvider class.</p> <p>// ExpiringLicenseProvider.cs</p> <p>//</p> <p>Using system;</p> <p>Using system.diagnostics;</p> <p>USING SYSTEM.GLOBALIZATION;</p> <p>Namespace licensedControls {</p> <p>Public Class ExpiringLicenseProvider: ServerLicenseProvider {</p> <p>Protected Override ServerLicense CreateLicense (Type Type, String</p> <p>Key) {</p> <p>String [] parts = key.split (';');</p> <p>Debug.assert (Parts.length == 2);</p> <p>Return New ExpiringLicense (Type, Key, Int32.parse (Parts [1],</p> <p>CultureInfo.invariantculture);</p> <p>}</p> <p>Protected Override Bool ValidateLicense (ServerLicense License, Out</p> <p>String ErrorMessage) {</p> <p>ErrorMessage = NULL; ExpiringLicense Testlicense = (ExpiringLicense) license;</p> <p>Testlicense.incrementusageCounter ();</p> <p>IF (Testlicense.isexpired) {</p> <p>ErrorMessage = "The license for" </p> <p>Testlicense.licensedType.Name "HAS EXPIRED."</p> <p>Return False;</p> <p>}</p> <p>Return True;</p> <p>}</p> <p>Protected Override Bool ValidateLicensedata (Type Type, String</p> <p>Licensedata) {</p> <p>String [] parts = licensedata.split (';');</p> <p>IF (parts.length == 2) {</p> <p>Return Base.ValidateLicensedata (Type, Parts [0]);</p> <p>}</p> <p>Else {</p> <p>Return False;</p> <p>}</p> <p>}</p> <p>}</p> <p>}</p> <p>The EXPIRINGENSEPROVIDER class is derived from ServerLicenseProvider, which covers the following methods of the base class:</p> <p>• 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: "<full Type> IS licensed.; <Use count>".</p> <p>The ExpiringLicenseProvider class uses the ExpiringLicense class as its license type.</p> <p>// ExpiringLicense.cs</p> <p>//</p> <p>Using system;</p> <p>Namespace licensedControls {</p> <p>Public Class ExpiringLicense: ServerLicense {</p> <p>Private Int_usagelimit;</p> <p>Private int _usagecount;</p> <p>Public ExpiringLicense (Type Type, String Key, int usagelimit):</p> <p>Base (Type, Key) {</p> <p>_USAGELIMIT = usagelimit;</p> <p>}</p> <p>Public Bool ISEXPIRED {</p> <p>Get {</p> <p>Return_usagecount> _usagelimit;</p> <p>}</p> <p>}</p> <p>Public void incrementusageCounter () {</p> <p>_USAGECUNT ;</p> <p>}</p> <p>}</p> <p>}</p> <p>The EXPIRINGLICENSE class implements the following logic:</p> <p>• 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.</p> <p>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.</p> <p>// ExpiringLicensedLabel.cs</p> <p>//</p> <p>Using system;</p> <p>Using system.componentmodel;</p> <p>Using system.Web.ui.webcontrols;</p> <p>Namespace licensedControls {</p> <p>[</p> <p>LicenseProvider (typeof (ExpiringLicenseProvider))</p> <p>]</p> <p>Public class expiringlicensedLabel: label {</p> <p>Public expiringlicensedlabel () {</p> <p>LicenseManager.validate (typeof (expiringlicensedlabel);</p> <p>}</p> <p>}</p> <p>}</p> <p>The contents of the.lic file in ExpiringLicenSedlabel are "licensedControls.exPiringLicensedLabel is licensed.; 5".</p> <p>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).</p> <p>Back to top</p> <p>Encrypted license scheme</p> <p>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.</p> <p>// EncryptedLicenseProvider.cs</p> <p>//</p> <p>Using system;</p> <p>Using system.diagnostics;</p> <p>Using system.io;</p> <p>Using system.security.cryptography;</p> <p>Namespace licensedControls {</p> <p>Public Class EncryptedLicenseProvider: ServerLicenseProvider {</p> <p>// this is a 64-bit key generated from the string</p> <p>// "5fb281f6".</p> <p>//</p> <p>Private static readonly byte [] encryptionKeybytes =</p> <p>New byte [] {0x35, 0x46, 0x42, 0x32, 0x38, 0x31, 0x46, 0x36};</p> <p>Protected Override Stream GetLicenSedataStream (Type Type) {</p> <p>Stream BaseStream = Base.GetLicensedataStream (TYPE);</p> <p>IF (BaseStream == Null) {</p> <p>Return NULL;</p> <p>}</p> <p>DescryptoServiceProvider DES = New DescryptoserviceProvider (); des.key = encryptionKeybytes;</p> <p>DES.IV = EncryptionKeybytes;</p> <p>Icryptotransform deSDecryptor = des.createdecryptor ();</p> <p>Return New CryptostReam (BaseStream, Desdecryptor,</p> <p>CryptostReammode.read;</p> <p>}</p> <p>}</p> <p>}</p> <p>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.</p> <p>ServerLicense is ideal for licensed classes as EncryptedLicenseProvider, so there is no need to implement any derived license classes for this permit provider.</p> <p>The EncryptedLicensedLabel control shown in the following code uses the license scheme implemented in the EncryptedLicenseProvider class.</p> <p>// encryptedLicensedLabel.cs</p> <p>//</p> <p>Using system;</p> <p>Using system.componentmodel;</p> <p>Using system.Web.ui.webcontrols;</p> <p>Namespace licensedControls {</p> <p>[</p> <p>LicenseProvider (IPRYPTEDLICENSEPROVIDER)</p> <p>]</p> <p>Public class encryptedLicensedLabel: label {</p> <p>Public EncryptedLicenSedlabel () {</p> <p>LicenseManager.validate (typeptedLicensedLabel);</p> <p>}</p> <p>}</p> <p>}</p> <p>The figure below shows the .lic file associated with EncryptedLicensedLabel.</p> <p>Figure 3. Content of the licensedControls.EncryptedLicensedlabel file</p> <p>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.</p> <p>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.</p> <p>Back to top</p> <p>Authorization implementation checklist</p> <p>The following table describes the tasks that need to be executed when implementing the authorization of the server control:</p> <p>• 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</p> <p>summary</p> <p>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.</p> <p>Go to the original English page</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-105569.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="105569" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.037</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'w7eAr1ovBz7MezjdrYB_2F1O2isl_2Fcnavn_2B8_2FngPMRRtqiFGnxyQL37z7nI_2FJhqrh1MLorreCbuPChv1ToMYK2cQ_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>