Implementierung von Lizenzmodellen in .NET, Teil 2

Know-how  –  0 Kommentare

Theoretische Überlegungen sind die eine Seite der Lizenzproblematik. Am Ende der entscheidet aber die praktische Umsetzung über die Tauglichkeit der entwickelten Herangehensweise. Welche Kriterien zu berücksichtigen sind und welche Lösungen im Falle der .NET Plattform in eine engere Auswahl kommen sollten, ist Thema dieses Artikels.

Nach den ganzen Vorüberlegungen wird es irgendwann Zeit, das ausgewählte beziehungsweise selbst erdachte Lizenzmodell auch in die Tat umzusetzen. Oft stellt sich die Frage, ob es selbst implementiert oder von Dritten eingekauft werden soll. Im Folgenden gibt es ein paar Auswahlkriterien an die Hand, die für beide Aspekte gelten.

Je nach zu lizenzierender Software muss eventuell auch die Lizenzbibliothek für mehrere Plattformen zur Verfügung stehen. Insbesondere dann, wenn der (Fat-)Client selbst einen Teil des Lizenzmodells enthält, was in der Regel mindestens für die Validierung der Fall ist. Eine Alternative ist das komplette Ausweichen auf einen externen, selbstimplementierten Service, der die Lizenzvalidierung übernimmt. In dem Fall sind nur allgemeine Daten zu übertragen.

Bei .NET heißt eine breite Plattformenabdeckung mindestens das Einbeziehen der aktuellsten zwei bis drei .NET-Versionen. Ganz komfortabel wird es, wenn ein Portable-Class-Library-Profil zur Verfügung steht, das vielleicht sogar die mobile Seite abdeckt, falls das ein Thema ist.

Auch das Datenformat für die Lizenzinformationen ist ein oft diskutiertes Thema. Zu häufig wird hier auf das Prinzip Security by Obscurity gesetzt. Nur weil Lizenzinformationen nicht einsehbar sind, heißt das nicht, dass sie sicher verpackt wurden. Das Speicherformat für Lizenzinformationen sollte so offen wie möglich sein. Es spricht nichts gegen eine im Klartext lesbare Datei, so lange die darin enthaltenen Daten durch eine Signatur oder ähnliches geschützt sind. Das hat den großen Vorteil, dass sich etwa im Supportfall jeder kurz einen Überblick verschaffen kann, was denn lizenziert ist. Änderbar sind die Informationen trotzdem nicht. Ein proprietäres Format ist oft keine gute Idee – insbesondere wenn das Format von einem zugekauften Anbieter stammt–, weil es die Abhängigkeiten zu diesem noch weiter in die Höhe treibt.

Beim Thema Sicherheit wird es noch interessanter. Oft werden kritische Teile, wie die Absicherung der Lizenzinformationen, selbst in die Hand genommen. Zu oft geht das allerdings schief. Was nicht selbst programmiert werden sollte, sind beispielsweise Funktionen zur Verschlüsslung. Hier gibt es in den gängigsten Programmiersprachen genug vorgefertigte Algorithmen, die nur mit ein paar Daten gefüttert werden müssen, um eine Absicherung vorzunehmen. Es bietet sich an, auf derartig bereitgestellte Funktionen zurückgreifen.

Wer diese drei Hauptpunkte beachtet, je nach Anwendungsfall gibt es noch zahlreiche weitere, muss nicht nach einiger Zeit feststellen, dass die gewählte Implementierung zu schnell nicht mehr den wachsenden Anforderungen entspricht. Und eine Lizenzierung nachträglich zu ändern, haben schon viele Firmen teuer bezahlt.

Im Allgemeinen muss eine Bibliothek, externe Komponenten oder die selbstimplementierte Lizenzierung das gewünschte Lizenzmodell unterstützten, das Policy Pattern abbilden können, sich in den aktuellen Entwicklungsprozess integrieren lassem und zur Lizenzierungsprozedur passen, die im Unternehmen etabliert ist oder etabliert werden soll.

Seit der Version 1.1 des .NET Framework, also seit 2003, ist ein Lizenzprovider im .NET Framework integriert. Auslöser war der RAD-Ansatz (Rich Application Developmen), der damals stark propagiert wurde. Ziel ist es daher insbesondere, eigene Windows-Forms-Anwendungen und eigene Controls mit einer Lizenzierung auszustatten, ohne auf externe Bibliotheken oder fremde Anbieter zurückgreifen zu müssen. Erfreulicherweise lässt sich diese Art der Lizenzierung auch auf beliebige Klassen anwenden. Die Ableitung der Control-Klasse, die häufig als Nachteil genannt wird, ist keine Voraussetzung.

Das .NET-Lizenzierungsmodell, wie es im Folgenden genannt wird, besteht aus den Klassen LicenseManager, LicenseProvider, LicFileLicenseProvider, License und LicenseException. Kombinationen aus ihnen ergeben einen vergleichsweise flexiblen Lizenzierungs-Workflow. Im Standard legt er Dateien mit der Lizenzinformation zugrunde, die der LicFileLicenseProvider einliest. Abbildung 1 zeigt die Abhängigkeiten der oben genannten Klassen.

Abhängigkeiten des in .NET integrierten Lizenzproviders (Abb. 1)


Zentraler Punkt ist der LicenseManager, der ziemlich genau dem aus diversen Policy Patterns entspricht. Die Logik zur Validierung einer Lizenz ist zwar vorhanden, allerdings fehlt der Code, um eine konkrete Lizenz zu beschaffen. Die Aufgabe übernimmt wiederum der LicenseProvider. Allerdings ist das nur eine Basisklasse, die bestimmte allgemeingültige Mechanismen bereitstellt. Eine konkrete Implementierung findet sich in der schon angesprochenen Klasse LicFileLicenseProvider, die Lizenzinformationen aus einer Datei einliest. Zu guter Letzt stellt die Klasse License die abstrakte Sicht der Lizenzinformationen im Code dar.

[LicenseProvider(typeof(LicFileLicenseProvider))]
public partial class DemoControl : UserControl
{
private License license = null;

public DemoControl()
{
InitializeComponent();

// Validate the license of this particular control.
license = LicenseManager.Validate(typeof(DemoControl), this);
}
}

Der oben gezeigte Code ist ein Beispiel für die Lizenzierung eines Demo-Kontrollelements. Die Lizenz wird in einer privaten Eigenschaft der Klasse gespeichert, nachdem sie im Konstruktor validiert wurde. Der Aufruf der Validate-Methode sorgt unter Angabe des zu lizenzierenden Typs und der konkreten Instanz des Typs für die Validierung. Da es sich um eine Basisklasse handelt, wird die Validierung an die konkrete Implementierung weitergereicht. Im vorliegenden Codeausschnit ist das der LicFileLicenseProvider, der über die LicenseProvider-Annotation dem Demo-Kontrollelement hinzugefügt wurde.

protected virtual string GetKey(Type type)
{
return string.Format(CultureInfo.InvariantCulture,
"{0} is a licensed component.", new object[]
{
type.FullName
});
}

Die oben dargestellte Implementierung der GetKey-Methode des LicFileLicenseProvider ist so einfach gestrickt, dass sie sich nicht für den Produktiveinsatz eignet. In ihr wird lediglich eine vom zu lizenzierenden Typ abhängige Zeichenkette zurückgeliefert. Dieser Typ wurde der Validate-Methode übergeben. Zwar macht die Implementierung den Einsatz des .NET-Lizenzproviders ersichtlich, sie ist aber dringend durch eine gute LicenseProvider-Implementierung zu ergänzen. Woher die Informationen zur Lizenz kommen, spielt dann keine Rolle mehr. Zumindest nicht aus Sicht des .NET-Lizenzproviders.

Die Trennung von LicenseManager und LicenseProvider erlaubt das Implementieren verschiedener Lizenzierungsarten – ein wesentlicher Aspekt für die Flexibilität eines Lizenzierungssystems.