Skip to content

Anwendungsfälle

Aktivieren, deaktivieren & Plätze verschieben

Binden Sie einen Schlüssel an eine Maschine, geben Sie diesen Platz frei, damit der Kunde auf eine neue wechseln kann, und tun Sie das für Test-, Jahres- und unbefristete Lizenzen — online, offline/netzwerkisoliert (air-gapped) oder anbieterseitig, wenn eine Maschine nicht mehr existiert — mit genau dem, was Ihre App in jedem Fall sieht.

Ziel

Machen Sie aus einem Lizenzschlüssel eine laufende, lizenzierte Installation auf einer bestimmten Maschine — und lassen Sie den Kunden (oder sich selbst) diesen Platz später freigeben, damit er auf eine andere Maschine wechseln kann, ohne einen weiteren Platz zu kaufen. Das ist der alltägliche Aktivierungslebenszyklus: Aktivieren bindet einen Schlüssel an eine Maschine und belegt einen Platz; Deaktivieren gibt ihn frei; derselbe Schlüssel funktioniert für Test-, Jahres- (befristete) und unbefristete Lizenzen.

Der Code unten ist C# (Keyright.NET), aber die Form des SDK ist in den Node-, Python- und Java-Paketen identisch — siehe das lauffähige Samples-Repository.

Wann Sie es einsetzen

  • Verwenden Sie dies für den normalen Ablauf: Ein Kunde gibt seinen Schlüssel ein und Ihre App aktiviert; später mustert er einen Laptop aus und möchte diesen Platz zurück.
  • Verwenden Sie den anbieterseitigen Pfad, wenn eine Maschine defekt, neu aufgesetzt oder unerreichbar ist und der Kunde den Platz nicht selbst freigeben kann.
  • Verwenden Sie den Offline-Pfad für eine Maschine, die den Service überhaupt nicht erreichen kann — Sie stellen einen signierten Lease aus, der an genau diese eine Maschine gebunden ist.
  • Greifen Sie nicht hierzu, um zu ändern, was eine Lizenz gewährt — Ablauf, Plätze und Verlängerungen werden unter Verlängerung/Ablauf behandelt, und welche Produktversionen sie abdeckt, steht in Upgrades verkaufen & Versionen steuern.

Die drei Lizenzformen

Eine Lizenz trägt ein Tier, eine Platzanzahl, ein optionales Ablaufdatum und ein optionales Trial-Flag. Diese ergeben zusammen die drei Formen, die Ihre Kunden sehen:

FormExpiryUtcIsTrialWas Ihre App anzeigt
Unbefristetnullfalse„Licensed — perpetual“
Jahres- / befristetein Datumfalse„Licensed — expires 31 Dec 2027“
Testversion / Evaluierungein Datumtrue„Evaluation — expires 31 Dec 2027 (N days left)“

In Ihrem Code

Ihre App liest all das aus der LicenseInfo, die Activate/Validate zurückgeben — Sie parsen nie selbst einen Schlüssel-String:

var info = await client.ActivateAsync(licenseKey);
if (info.Status != LicenseStatus.Valid)      // fail-closed
    return ShowUnlicensed(info.Message);

string banner = info.IsTrial
    ? $"Evaluation — expires {info.ExpiryUtc:d} ({info.DaysRemaining} days left)"
    : info.ExpiryUtc is null
        ? "Licensed — perpetual"
        : $"Licensed — expires {info.ExpiryUtc:d}";

Aktivieren (online)

ActivateAsync(key) sendet den Fingerabdruck der Maschine und den Schlüssel an den Issuing-Service. Der Service prüft die Platzanzahl, bindet die Lizenz an diese Maschine und liefert einen signierten Lease zurück, den das SDK lokal zwischenspeichert. Von da an arbeitet Validate() offline gegen diesen zwischengespeicherten Lease (siehe Sicherheit & das Lease-Modell).

Das erneute Aktivieren derselben Maschine ist idempotent — es aktualisiert den Lease und belegt nie einen zweiten Platz. ActivateAsync bei jedem Start aufzurufen (wenn online) ist das empfohlene Muster: Es hält den Lease stillschweigend aktuell.

Der Aufruf hat in jedem SDK dieselbe Form, und über rohes HTTP ist es ein einzelner POST an /v1/activate, der den zu cachenden signierten Lease zurückliefert:

.NET

LicenseInfo info = await License.ActivateAsync(customerEnteredKey, ct);
if (info.IsValid && info.IsPaid) ShowLicensedUi(info.StatusBadge);   // Lease zwischengespeichert; läuft offline, bis er abläuft
else ShowActivationError(info.Message);                              // bleibt Free, z. B. "All seats … are in use."

Node.js

const info = await license.activate(customerEnteredKey);
if (info.isValid && info.isPaid) showLicensedUi(info.statusBadge);
else showActivationError(info.message);

Python

info = license.activate(customer_entered_key)
if info.is_valid and info.is_paid:
    show_licensed_ui(info.status_badge)
else:
    show_activation_error(info.message)

Java

LicenseInfo info = client.activate(customerEnteredKey);
if (info.isValid() && info.isPaid()) showLicensedUi(info.statusBadge());
else showActivationError(info.message());

Beliebige Sprache (rohes HTTP)

curl -s -X POST "$BASE/v1/activate" -H "content-type: application/json" \
  -d '{"key":"LIC-…","machineId":"<stable-machine-id>","product":"acme-app"}'
# status:"ok" liefert einen signierten "lease"-String — speichern Sie ihn unverändert und verifizieren Sie ihn selbst offline.
# Verhalten Sie sich fail-closed bei jedem anderen Status, einem Nicht-2xx-Code oder einem Lease, der sich nicht verifizieren lässt.

Aktivierung einer Testversion. Ein Testschlüssel wird genau wie ein bezahlter Schlüssel aktiviert — derselbe Aufruf, dasselbe Platzmodell — er kommt lediglich mit IsTrial == true und einem Ablaufdatum zurück:

var info = await client.ActivateAsync(trialKey);
// info.IsTrial == true, info.ExpiryUtc == das Ende der Testversion, info.DaysRemaining zählt herunter

Zeigen Sie das Evaluierungs-Banner an und schalten Sie hinter info.IsTrial, was immer Sie möchten. Ist das Testdatum überschritten, liefert Aktivierung/Validierung LicenseStatus.Expired, und Sie fallen in Ihren unlizenzierten Zustand zurück. Testversionen berücksichtigen die Dauer ab der ersten Aktivierung und erkennen Uhrmanipulation — ein Kunde kann durch Zurückstellen der Uhr keine Zeit zurückgewinnen (siehe die Sicherheitsseite). Testversionen werden üblicherweise per Self-Service von Ihrer eigenen Website bezogen; siehe Eine kostenlose Testversion anbieten.

Unbefristete Aktivierung. Eine unbefristete Lizenz hat kein Ablaufdatum. Einmal aktivieren; ExpiryUtc ist null, also läuft Ihr „unbefristet“-Zweig. Der Lease hat weiterhin eine kurze TTL und wird bei der nächsten Online-Aktivierung aktualisiert — die Lizenz läuft nie ab, aber der Offline-Lease bleibt ein kurzlebiges Kulanz-Token (genau das verhindert, dass eine unbefristete Lizenz offline auf beliebig viele Maschinen kopiert wird).

Jahres- / befristete Aktivierung. Identischer Aufruf; ExpiryUtc ist das Datum, bis zu dem bezahlt wurde. Verwenden Sie info.IsExpiringSoon() / info.DaysRemaining, um Kunden vor der Verlängerung zu erinnern. Nach dem Datum liefert die Aktivierung Expired. Die Verlängerung ist eine anbieterseitige Änderung an der Lizenz (POST /admin/licenses/{id}/renew) — der Kunde behält denselben Schlüssel und aktiviert einfach erneut, um das neue Ablaufdatum zu übernehmen.

Wenn keine Plätze mehr frei sind. Versucht eine neue Maschine, eine Lizenz zu aktivieren, deren Plätze alle belegt sind, liefert der Service LicenseStatus.SeatLimit — zeigen Sie eine klare Meldung „alle Plätze belegt — geben Sie zuerst einen frei“ an. (Auch hier gilt: Dieselbe Maschine, die erneut aktiviert, läuft nie hier hinein.)

Die Keyright-Lizenzliste für Acme App; jede Zeile zeigt den Lizenznehmer, die Edition, eine Spalte SEATS mit Belegt-von-Gesamt-Zählern (Stark Industries 2/3, Wayne Enterprises 0/10, Globex Corporation 1/25, Acme Inc. 1/3), ein Ablaufdatum und ein Status-Badge — active, revoked, expired sowie eine „in 10 days“-Warnung für baldigen Ablauf bei Initech LLC.
Die Lizenzliste zeigt belegte / gesamte Plätze pro Lizenz, sodass Sie auf einen Blick sehen, welche Schlüssel noch einen freien Platz haben, bevor eine neue Maschine aktiviert.

Eine Maschine wechseln (vom Kunden ausgelöste Deaktivierung)

Die Deaktivierung gibt den Platz dieser Maschine frei und löscht den lokalen Lease, sodass der Platz sofort anderswo verfügbar ist. So wechselt ein Kunde die Maschine: auf der alten Maschine deaktivieren, dann auf der neuen aktivieren, die den freigegebenen Platz übernimmt. Jedes SDK bietet denselben Aufruf, und über rohes HTTP ist es POST /v1/free-seat:

.NET

await License.DeactivateAsync(key);   // gibt den Platz dieser Maschine frei und löscht den zwischengespeicherten Lease

Node.js

const status = await license.deactivate(key);   // 'ok' | 'not_found'; wirft, wenn der Service nicht erreichbar ist

Python

status = license.deactivate(key)   # "ok" | "not_found"; löst eine Exception aus, wenn der Service nicht erreichbar ist

Java

String status = client.deactivate(key);   // "ok" | "not_found"; wirft IllegalStateException, wenn nicht erreichbar

Beliebige Sprache (rohes HTTP)

curl -s -X POST "$BASE/v1/free-seat" -H "content-type: application/json" \
  -d '{"key":"LIC-…","machineId":"<stable-machine-id>","product":"acme-app"}'
# -> {"status":"ok"} — löschen Sie gleichzeitig Ihren zwischengespeicherten Lease

Die Deaktivierung hat in keinem SDK einen Offline-Fallback — das Freigeben eines Platzes ist eine serverseitige Änderung, daher schlägt der Aufruf fehl (wirft/löst eine Exception aus), wenn der Service nicht erreichbar ist. Das funktioniert für unbefristete, Jahres- und Testlizenzen gleichermaßen. Nach der Deaktivierung liefert Validate() auf dieser Maschine NoLicense.

Was Sie tun (Anbieterseite)

Einen Platz für den Kunden freigeben (erzwungene Deaktivierung)

Wenn eine Maschine ausfällt, neu aufgesetzt wird oder ein Kunde nicht mehr an sie herankommt, geben Sie den Platz aus Ihrem Backend frei — ohne Client.

Dashboard: Öffnen Sie die Lizenz in der Ansicht Licenses, sehen Sie sich ihre aktiven Maschinen an und geben Sie die nicht mehr vorhandene frei.

Die Lizenzseite „Stark Industries“ in Keyright: ein Devices-Panel mit 2 von 3 belegten Plätzen und den Maschinen-IDs WORKSTATION-STAR und DESKTOP-STARK-01, jeweils als online markiert mit einem „lease renews by“-Datum und einem Button „Free seat“; eine Details-Karte mit der Edition pro, 3 Plätzen (2 belegt), unbefristeter Laufzeit und Entitlements; sowie die Aktionen Renew, Add seats, License file und Send portal link über den Tabs.
Das Devices-Panel einer Lizenz: Jede gebundene Maschine zeigt einen Button Free seat, mit dem Sie einen Platz zurückgeben können, wenn eine Maschine defekt oder neu aufgesetzt ist — und License file stellt einen Offline-Lease für einen netzwerkisolierten (air-gapped) Platz aus.

API:

curl -X POST "https://keyright.delta1labs.com/admin/licenses/<KEY>/free-seat" \
     -H "X-Admin-Token: $KEYRIGHT_ADMIN_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"machineId":"KRM1:..."}'

POST /admin/licenses/{id}/free-seat ist Support+; POST /admin/licenses/{id}/deactivate (Admin+) tut dasselbe. Das nächste Online-Validate() der Maschine sieht, dass der Platz weg ist. Die Maschinen einer Lizenz können Sie mit GET /admin/licenses/{id}/activations auflisten.

Offline-/Air-Gapped-Aktivierung

Für eine Maschine, die den Service überhaupt nicht erreichen kann, stellt der Anbieter einen langlebigen signierten Lease aus, der an genau diese eine Maschine gebunden ist. Das funktioniert für Test- und bezahlte Lizenzen identisch.

  1. Auf der Offline-Maschine deren ID auslesen:

    var machineId = MachineFingerprint.Current().ToBoundString();  // KRM1:...

    (oder keyright machine-id ausführen). Senden Sie diesen String an den Anbieter.

  2. Der Anbieter (mit Konnektivität + einem Admin-Token) stellt einen Lease für diese Maschine aus — Standard-TTL 365 Tage:

    curl -X POST "https://keyright.delta1labs.com/admin/licenses/<KEY>/offline-lease" \
         -H "X-Admin-Token: $KEYRIGHT_ADMIN_TOKEN" \
         -H "Content-Type: application/json" \
         -d '{"machineId":"KRM1:...","days":365}'   > offline-lease.json

    Das bestätigt einen Platz für diese Maschine (Offline-Aktivierungen zählen also weiterhin gegen das Platzlimit — Sie können nicht über die Platzanzahl hinaus beliebig viele Offline-Leases ausstellen).

  3. Zurück auf der Offline-Maschine importieren Sie ihn — ohne Netzwerkbeteiligung:

    client.ImportOfflineLease(File.ReadAllText("offline-lease.json"));
    var info = client.Validate();   // Valid, vollständig offline

Da der Lease an den Fingerabdruck dieser Maschine gebunden ist, ist die Datei auf jeder anderen Maschine nutzlos (sie liefert MachineMismatch). Siehe die Sicherheitsseite, warum das auch offline gilt, und Offline / netzwerkisoliert betreiben für die vollständige Offline-Geschichte.

Vollständig offline, ganz ohne Service

Wenn Sie nie möchten, dass die Maschine (oder der Anbieter) ein Netzwerk berührt, signieren Sie mit der CLI eine eigenständige Offline-Lizenzdatei und liefern sie mit dem Produkt aus:

keyright license --sign --licensee "Acme Corp" --product yourapp --tier pro \
  --private-key yourapp.private.json --expiry 2027-12-31 --out license.json

Der Client validiert sie rein offline über Validate() (sie wird über den Pfad, die Umgebungsvariable KEYRIGHT_LICENSE oder den Standard-App-Data-Speicherort gefunden). In diesem Modus gibt es keine Platzverfolgung — er ist die richtige Wahl für wirklich netzwerkisolierte (air-gapped) oder eingebettete Bereitstellungen.

Ein Hinweis zur Offline-Deaktivierung

Es gibt heute keinen clientseitig erzeugten „Deaktivierungsnachweis“, daher kann eine netzwerkisolierte (air-gapped) Maschine ihren Platz nicht selbst zurückgeben. Geben Sie ihn anbieterseitig frei (erzwungene Deaktivierung, siehe oben), sobald Ihr Backend Konnektivität hat, oder stellen Sie Offline-Leases mit einer so kurzen TTL aus, dass der Platz einer stillgelegten Maschine von selbst zurückkommt, wenn der Lease ausläuft. Siehe das Samples-Repository.

Cloud vs. Self-Hosting

Der Aktivierungsablauf ist in beiden Modi identisch. Nur die Endpunkte ändern sich:

  • Laufzeitaufrufe (/v1/activate, /v1/validate, /v1/free-seat) zeigen auf Ihre ServiceUrl — https://keyright.delta1labs.com auf Keyright Cloud, die URL Ihres eigenen Issuing-Service bei Self-Hosting.
  • Anbieterseitige Aufrufe (/admin/licenses/...) verwenden dasselbe $BASE und ein Admin-Token. Auf Keyright Cloud stammt das Token aus Ihrer Dashboard-Anmeldung; bei Self-Hosting ist es Ihr Mandanten-/Umgebungs-Admin-Token.
  • Platzbindung, Leases und die Offline-Pfade verhalten sich in beiden Fällen gleich.

Prüfen

  1. Aktivieren Sie einen Schlüssel auf Maschine A und bestätigen Sie LicenseInfo.Status == Valid und das richtige Banner (Testversion / befristet / unbefristet). Die Liste Licenses → activations des Dashboards zeigt Maschine A.
  2. Aktivieren Sie denselben Schlüssel erneut auf Maschine A — bestätigen Sie, dass kein zweiter Platz belegt wird (Platzanzahl unverändert).
  3. Bestätigen Sie, dass Sie von einer neuen Maschine B bei voll belegten Plätzen LicenseStatus.SeatLimit erhalten.
  4. DeactivateAsync auf A (oder anbieterseitig free-seat), dann auf B aktivieren — B übernimmt jetzt den freigegebenen Platz, und das Dashboard spiegelt den Wechsel wider.

Siehe auch