Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 5/2011.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Zusammenfassung

Erfahren Sie, wie Sie den Zugriff auf die Funktionen einer Datenbank durch Benutzerdaten einschränken können.

Techniken

Verschlüsselung, VBA

Voraussetzungen

Access 2000 und höher

Beispieldateien

Registrierung.mdb

Shortlink

www.access-im-unternehmen.de/797

Registrierung von Anwendungen

André Minhorst, Duisburg

Wenn Sie eine Anwendung programmieren und später als Lösung verkaufen möchten, müssen Sie auf irgendeine Weise sicherstellen, dass nur der jeweilige Käufer damit arbeiten kann. Anderenfalls passiert es leicht, dass dieser die Anwendung an andere Nutzer weitergibt - vielleicht sogar ohne das Bewusstsein, dass er den Hersteller der Software um seinen Lohn bringt. In diesem Beitrag stellen wir Ihnen eine Lösung vor, mit der Sie Ihre Anwendungen vor der Weitergabe an Dritte schützen - und das sogar mit zeitlicher Begrenzung.

Bei der in diesem Beitrag beschriebenen Lösung gehen wir zunächst davon aus, dass der Benutzer sich eine Anwendung aus dem Internet herunterlädt oder diese per E-Mail von Ihnen erhält.

Nach der Installation soll die Anwendung beim ersten Start prüfen, ob der Benutzer einen Satz von Registrierungsdaten eingegeben hat, die aus einem Benutzernamen und einem Registrierungsschlüssel bestehen.

Ist dies geschehen und sind die Registrierungsdaten gültig, sollen diese Daten irgendwo in der Anwendung gespeichert werden und die Anwendung starten.

Bei jedem folgenden Aufruf liest die Anwendung die gespeicherten Registrierungsdaten automatisch aus und bricht den Start entweder ab oder führt die Anwendung aus - je nachdem, ob die Registrierungsdaten noch gültig sind.

Bindung des Registrierungsschlüssels an den Benutzernamen

Damit der Registrierungsschlüssel nicht von beliebigen Benutzern verwendet werden kann, wird dieser mindestens auf Basis des Benutzernamens erstellt. Für die Verschlüsselung des Namens und somit die Erstellung des Registrierungsschlüssels verwenden wir die in der Klasse clsCrypt enthaltenen Algorithmen etwa zum Berechnen eines SHA1-verschlüsselten Ausdrucks (Quellenangabe siehe Beispieldatenbank).

SHA steht für Secure Hash Algorithm. Dieser Algorithmus soll einen eindeutigen Prüfwert etwa für eine Zeichenkette liefern, also einen Wert, der vom Inhalt der Zeichenkette abhängt.

Wenn Sie also sicherstellen möchten, dass die Anwendung nur von einem Benutzer verwendet wird, der als Benutzername seinen Namen und als Registrierungsschlüssel den Hash-Wert einsetzt, brauchen Sie nur einen solchen Wert zu berechnen und später beim Start der Anwendung zu prüfen, ob die Kombination dieser beiden Werte zusammenpasst.

Den Aufruf der Methode GetSHA1 dieser Klasse haben wir wie in Listing 1 im Modul mdlTools gekapselt.

Listing 1: Aufruf der Verschlüsselungsfunktionen der Klasse clsCrypt

Public Function GetSHA1(strKey As String) As String

    Dim objCrypt As New clsCrypt

    Dim strSHA1 As String

    strSHA1 = objCrypt.GetSHA1(strKey)

    GetSHA1 = strSHA1

    Set objCrypt = Nothing

End Function

Im Direktfenster testen Sie diese Funktion etwa so:

? GetSHA1("Klaus Müller")

04538C3BBD1B721D87F6570B577D1D0A3E7390AD

Angenommen, Sie hätten einem Klaus Müller diese Kombination aus Benutzername und Registrierungsschlüssel geschickt, muss er diese beim ersten Start einer Anwendung eingeben.

Die Kombination wird dann irgendwo in der Datenbank gespeichert, damit der Benutzer diese beim nächsten Start nicht erneut eingeben muss. Dies könnte beispielsweise in einer eigens dafür eingerichteten Tabelle geschehen. Diese nennen Sie tblRegistrierung und legen die beiden Felder Benutzername und Registrierungsschluessel an, sodass die Tabelle wie in Abb. 1 aussieht.

pic001.png

Abb. 1: Tabelle zum Speichern der Benutzerdaten

Formular beim Öffnen anzeigen

Nach dieser Vorbereitung benötigen wir einen Ort, an dem wir die Prüfung der Benutzerdaten durchführen - sofern diese überhaupt bereits vorliegen. Dafür legen Sie ein Formular an, das an die Tabelle tblRegistrierung gebunden ist und den Namen frmStart erhält. Legen Sie dieses Formular in den Access-Optionen als Startformular fest, sodass dieses gleich nach dem Start der Anmeldung erscheint.

Das Formular enthält vier Steuerelemente: zwei Textfelder namens txtBenutzername und txtRegistrierungsschluessel, die an die beiden Felder der Datenherkunft gebunden sind, sowie zwei Schaltflächen namens cmdOK und cmdAbbrechen (s. Abb. 2).

pic002.png

Abb. 2: Formular zur Eingabe der Benutzerdaten

Die Schaltfläche cmdAbbrechen soll die Eingabe der Benutzerdaten abbrechen und die Anwendung schließen. Dafür hinterlegen Sie für diese Schaltfläche die folgende Prozedur:

Private Sub cmdAbbrechen_Click()

    DoCmd.Quit

    End Sub

Stellen Sie außerdem die Eigenschaft Abbrechen der Schaltfläche auf den Wert Ja ein. Dies sorgt dafür, dass die Anwendung auch beim Betätigen der Escape-Taste geschlossen wird. Das Prüfen der Benutzerdaten erledigt eine kleine Funktion namens BenutzerdatenPruefen (s. Listing 2).

Listing 2: Prüfung der Benutzerdaten

Private Function BenutzerdatenPruefen() As Boolean

    BenutzerdatenPruefen = (GetSHA1(Nz(Me!txtBenutzername)) = Nz(Me!txtRegistrierungsschluessel))

End Function

Die Funktion ermittelt den Hash-Wert des Benutzernamens und vergleicht diesen mit dem für den Registrierungsschlüssel angegebenen Wert. Stimmen beide überein, liefert die Funktion den Wert True zurück.

Beim Öffnen des Formulars wird diese Funktion erstmalig aufgerufen. Dazu legen Sie für das Ereignis Beim Laden des Formulars die folgende Prozedur an:

Private Sub Form_Load()

    If BenutzerdatenPruefen Then

        DoCmd.Close acForm, Me.Name

        DoCmd.OpenForm "frmMain"

    End If

    End Sub

War die Prüfung erfolgreich, schließt die Prozedur einfach das aktuelle Formular und öffnet ein weiteres Formular namens frmMain, das beispielsweise dem Hauptformular der Anwendung entspricht. Sie können natürlich auch einfach das Formular schließen und die verfügbaren Funktionen in der Menüleiste oder im Ribbon anzeigen.

Stimmen der Hash-Wert des Benutzernamens und der Registrierungsschlüssel nicht überein, bleibt das Formular einfach geöffnet. Der Benutzer hat dann die Gelegenheit, die Benutzerdaten einzugeben. Die Eingabe beendet der Benutzer mit einem Klick auf die Schaltfläche OK, was die folgende Prozedur auslöst:

Private Sub cmdOK_Click()

    If BenutzerdatenPruefen Then

        DoCmd.Close acForm, Me.Name

        DoCmd.OpenForm "frmMain"

    Else

        MsgBox "Falsche Benutzerdaten."

    End If

    End Sub

Hier erfolgt die gleiche Prüfung wie beim Laden des Formulars. Im Erfolgsfall wird das Formular geschlossen und frmMain geöffnet. Stimmt die Kombination aus Benutzername und Registrierungsschlüssel nicht, erscheint eine Meldung mit dem Text Falsche Benutzerdaten. Der Benutzer kann dann erneut seine Daten eingeben oder mit einem Klick auf Abbrechen die Anwendung beenden (s. Abb. 3).

pic005.png

Abb. 4: Prinzipieller Ablauf beim Prüfen und Eingeben der Registrierungsdaten

Abb. 4 zeigt den prinzipiellen Ablauf beim Eingeben und Prüfen der Registrierungsdaten.

pic003.png

Abb. 3: Beim Eingeben falscher Benutzerdaten erscheint eine Meldung.

Anwendung schützen

Die bisherigen Bemühungen helfen nun natürlich nicht weiter, wenn Sie den Benutzer nicht vom Einsehen des Quellcodes abhalten. Dazu erstellen Sie aus der .mdb- oder .accdb-Anwendung eine .mde- oder .accde-Datenbank mit geschütztem Code und mit gesperrten Entwurfsansichten.

Der Benutzer kann den Mechanismus zum Prüfen der Benutzerdaten dann nicht einsehen und diesen nicht einfach reproduzieren, um selbst Zugangsdaten zu erzeugen.

Umgehen der Registrierung verhindern

Natürlich könnte der Benutzer einfach direkt auf die übrigen Formulare der Anwendung zugreifen, indem er diese über das Datenbankfenster oder den Navigationsbereich öffnet. Die Anzeige dieser Bereiche lässt sich zwar auch unterbinden, aber ein erfahrener Access-Entwickler kann diese dennoch anzeigen. Außerdem wäre hierfür der Einsatz des Sicherheitssystems erforderlich, was aber ab Access 2007 offiziell nicht mehr unterstützt wird.

Da wir den Entwurf und den Code von Formularen, Berichten und Modulen aber ohnehin schützen, können wir auch gleich einen Mechanismus in die Formulare einbauen, der vor dem Öffnen die Benutzerdaten prüft. Dies erreichen Sie beispielsweise durch eine ähnliche Prüfung wie im Startformular. Damit das Formular nicht geöffnet wird, wenn keine gültigen Benutzerdaten vorliegen, legen Sie die folgende Prozedur für das Ereignis Beim Öffnen des Formulars an:

Private Sub Form_Open(Cancel As Integer)

    Cancel = BenutzerdatenGueltig

    End Sub

Die Prüfung der Benutzerdaten haben wir derweil in eine eigene Funktion ausgegliedert, die sich im Modul mdlTools befindet (s. Listing 3).

Listing 3: Abgleich von Benutzername und Registrierungsschlüssel

Public Function BenutzerdatenGueltig() As Boolean

    Dim strBenutzername As String

    Dim strRegistrierungsschluessel As String

    strBenutzername = Nz(DLookup("Benutzername", "tblBenutzerdaten"))

    strRegistrierungsschluessel = Nz(DLookup("Registrierungsschluessel", "tblBenutzerdaten"))

    If Not GetSHA1(strBenutzername) = strRegistrierungsschluessel Then

        BenutzerdatenGueltig = True

    End If

End Function

Die Prozedur Form_Open prüft nun mithilfe der Funktion BenutzerdatenGueltig, ob die Tabelle tblBenutzerdaten einen gültigen Satz von Benutzerdaten enthält. Falls nicht, liefert BenutzerdatenGueltig den Wert False zurück, der gleich dem Parameter Cancel der Prozedur Form_Open übergeben wird. Dies bedeutet, dass der Öffnen-Vorgang des Formulars gleich unterbrochen und das Formular nicht geöffnet wird. Eine solche Prüfung müssten Sie zumindest den wichtigsten Formularen zuweisen, um die Anwendung ohne gültige Benutzerdaten unbenutzbar zu machen.

Zeitliche Komponente

Wie eingangs erwähnt, möchten Sie unter Umständen eine zeitliche Begrenzung der Nutzbarkeit der Anwendung mit den angegebenen Benutzerdaten erreichen. In diesem Fall müssten Sie ein Verfallsdatum erstellen oder mitgeben. Hier gibt es grundsätzlich zwei verschiedene Ansätze:

  • Sie legen selbst fest, bis zu welchem Datum die Benutzerdaten gültig sind.
  • Sie legen nur fest, wie lange der Betrieb unter den gegebenen Benutzerdaten möglich sein soll, den Start und somit auch den Endzeitpunkt legt der Benutzer selbst fest.

Die erste Variante ist einfach: Sie brauchen dazu nur das Enddatum in den Registrierungsschlüssel zu integrieren und diesen entweder beim ersten Aufruf oder bei jedem Aufruf zu prüfen. Das hört sich auf den ersten Blick kompliziert an, ist es aber nicht.

Nehmen wir an, Sie erstellen den Registrierungsschlüssel nicht nur auf Basis des Benutzernamens, sondern fügen noch das Datum hinzu - beispielsweise im Format yyyymmdd. Dies erledigt etwa die Funktion aus Listing 4.

Listing 4: Registrierungsschlüssel mit zusätzlichem Datum

Public Function RegistrierungsschluesselMitDatum(strBenutzer As String, datEnde As Date) As String

    Dim strEnddatum As String

    strEnddatum = Format(datEnde, "yyyymmdd")

    RegistrierungsschluesselMitDatum = GetSHA1(strBenutzer & strEnddatum)

End Function

Ein Aufruf über das Direktfenster sieht etwa so aus:

? RegistrierungsschluesselMitDatum("André Minhorst", "1.10.2011")

B9B555D12CB51D8F77C215CCE2402AF532545630

Wie aber ermitteln Sie beim Eingeben dieses Registrierungsschlüssels in der Anwendung das Enddatum, wenn dieses verschlüsselt im Registrierungsschlüssel steckt - der eigentlich nicht umkehrbar sein soll?

Ganz einfach: Sie durchlaufen einfach alle Daten vom heutigen Datum bis zu einem Datum, das der maximalen Laufzeit entspricht (also etwa 366 Tage für ein Jahr Laufzeit), und ermitteln so das passende Datum.

Diese Aufgabe erledigt die Funktion EnddatumErmitteln. Sie erwartet den Benutzernamen und den Registrierungsschlüssel als Parameter und durchläuft in einer Schleife alle Datumsangaben zwischen dem heutigen Datum und dem Datum in 366 Tagen.

Dabei erledigt sie für jeden Tag die gleiche Aufgabe wie beim Erzeugen des Registrierungsschlüssels: Sie setzt den Benutzernamen und das formatierte Datum zusammen, ermittelt den Hash-Wert für das jeweilige Datum und vergleicht diesen schließlich mit dem richtigen Hash-Wert. Wenn beide Hash-Werte übereinstimmen, wurde das Gültigkeitsdatum gefunden.

Immer prüfen oder nur einmal?

Sie können diese Prüfung nun zu jedem Start durchführen oder aber nur bei der ersten Registrierung. Sie würden dann das Datum ebenfalls in der Tabelle tblBenutzerdaten speichern und könnten dann direkt prüfen, ob die richtige Kombination aus Benutzername, Datum und Registrierungsschlüssel angegeben wurde. Die Tabelle tblBenutzerdaten würden Sie dann wie in Abb. 5 erweitern.

pic004.png

Abb. 5: Erweiterung der Tabelle tblBenutzerdaten um ein Datumsfeld

In diesem Fall ändern Sie die Funktion BenutzerdatenPruefen, die beim Öffnen des Formulars frmStart ausgeführt wird, wie in Listing 5.

Listing 6: Enddatum für die aktuellen Registrierungsdaten ermitteln

Public Function EnddatumErmitteln(strBenutzer As String, strRegistrierungsschluessel As String) As Date

    Dim datAktuell As Date

    Dim strEnddatum As String

    For datAktuell = Date To Date + 366

        strEnddatum = Format(datAktuell, "yyyymmdd")

        If GetSHA1(strBenutzer & strEnddatum) = strRegistrierungsschluessel Then

            EnddatumErmitteln = datAktuell

            Exit Function

        End If

    Next datAktuell

End Function

Diese Funktion prüft zunächst, ob das Feld Enddatum der Tabelle tblBenutzerdaten bereits einen Wert enthält. Falls ja, wird die Kombination aus Benutzername, Registrierungsschlüssel und Enddatum mithilfe der Funktion RegistrierungsschluesselMitDatum geprüft. Verläuft diese Prüfung positiv, liefert die Funktion BenutzerdatenPruefen den Wert True zurück.

Ist das Feld Enddatum der Tabelle tblBenutzerdaten noch nicht gefüllt, ruft die Routine zunächst die Funktion EnddatumErmitteln auf, um das für diese Kombination aus Benutzername und Registrierungsschlüssel gültige Enddatum zu ermitteln (s. Listing 6). Verläuft dies erfolgreich, wird das Enddatum in die Tabelle tblBenutzerdaten eingetragen und der Wert True als Funktionswert zurückgeliefert.

Zwischenfazit

Damit haben Sie bereits einen großen Teil der Arbeit erledigt: Unter dem angegebenen Benutzernamen kann die Anwendung nur noch bis zu einem bestimmten Datum verwendet werden.

Nun gibt es noch zwei Baustellen: Die Anwendung kann leicht auf mehreren Rechnern gleichzeitig eingesetzt werden - auch wenn dies unter ein und demselben Benutzernamen geschieht.

Und außerdem kann der Benutzer die Systemzeit seines Rechners zurückstellen und somit die Nutzungsdauer der Anwendung ins Unendliche verlängern.

Einschränkung der registrierten Kopien

Wenn Sie verhindern möchten, dass der Benutzer Ihre Anwendung auf Arbeitsplätzen in seiner gesamten Firma bereitstellt oder diese gar an Dritte weitergibt, sollten Sie die Registrierungsdaten zum Zeitpunkt der Registrierung einmalig an einen Webserver übermitteln.

Dort speichern Sie in einer Datenbank die Anzahl der Registrierungsvorgänge mit den gleichen Registrierungsdaten.

Beim Überschreiten einer bestimmten Anzahl können Sie dafür sorgen, dass der Benutzer sich bei Ihnen meldet. Wie Sie den Zugriff auf den Webserver erledigen, erfahren Sie im Beitrag Webservice light (www.access-im-unternehmen.de/798).

Zurückdrehen der Systemzeit erkennen

Um zu erkennen, ob der Benutzer die Systemzeit zurückgedreht hat, müssen Sie jeweils beim Start das aktuelle Datum speichern. Sollte die Systemzeit dann bei einem späteren Start vor dem gespeicherten Datum liegen, wäre ein Anhaltspunkt für eine Benutzung der Anwendung bei manipulierter Systemzeit gegeben.

Das kann allerdings auch durch Manipulation der Systemzeit in Richtung Zukunft ausgelöst werden: Angenommen, der Benutzer experimentiert gerade mit einer Technik, um die Nutzung seiner Anwendungen durch Benutzerdaten zeitlich einzuschränken.

Dieser könnte die Systemzeit auf ein Datum in der Zukunft einstellen, um zu prüfen, ob die Anwendung nach dem angegebenen Verfallsdatum noch funktioniert.

Wenn er nun genau zu diesem Zeitpunkt mit Ihrer Anwendung arbeitet, diese das in der Zukunft liegende Systemdatum speichert und der Benutzer dann die Systemzeit wieder zurückstellt, erhalten Sie den gleichen Effekt, als wenn der Benutzer die Anwendung zunächst regulär verwendet und dann für einen weiteren Einsatz nach Ablauf des Verfallsdatums die Systemzeit zurückdreht.

Und genauso kann es natürlich vorkommen, dass die Systemzeit gerade ein in der Zukunft liegendes Datum enthält und der Benutzer zufälligerweise genau dann die Anwendung installiert.

Wenn Sie es wirklich ernst meinen und die zeitliche Beschränkung der Nutzung durchsetzen möchten, bleibt Ihnen nichts anderes übrig, als das aktuelle Systemdatum zumindest einmal via Internet etwa von Ihrem eigenen Server einzulesen. Somit können Sie zumindest sicherstellen, dass beim Installieren das aktuelle Datum gespeichert wurde.

Zusammenfassung und Ausblick

Mit den hier vorgestellten Techniken erhalten Sie das Handwerkzeug, um die uneingeschränkte Weitergabe und Benutzung einer Anwendung zu unterbinden. Grundsätzlich ist dies zwar möglich, aber es würde wohl kaum jemand eine Anwendung mit seinen Registrierungsdaten weitergeben, wenn sein Name damit verbunden ist.

Listing 5: Datumsabhängige Registrierungsschlüssel prüfen

Private Function BenutzerdatenPruefen() As Boolean

    Dim datEnddatum As Date

    If IsNull(Me!enddatum) Then

        datEnddatum = EnddatumErmitteln(Me!txtBenutzername, Me!txtRegistrierungsschluessel)

        If Not datEnddatum = 0 Then

            Me!enddatum = datEnddatum

            BenutzerdatenPruefen = True

        End If

    Else

        If RegistrierungsschluesselMitDatum(Me!txtBenutzername, Me!enddatum) = Me!txtRegistrierungsschluessel Then

            BenutzerdatenPruefen = True

        End If

    End If

End Function

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Download

Download

Die .zip-Datei enthält folgende Dateien:

Registrierung.mdb

Beispieldateien downloaden

© 2003-2015 André Minhorst Alle Rechte vorbehalten.