Manchmal ist es erforderlich, Daten zwischen einer Anwendung, die in einem Browser ausgeführt wird, und einem Programm zu übertragen, das auf demselben System ausgeführt wird, auf dem der Browser ausgeführt wird. Dies kann beispielsweise erforderlich sein, wenn wir mit lokal angeschlossenen Geräten arbeiten müssen. Smartcard-Leser, Hardware-Verschlüsselungsschlüssel und so weiter.

Bild von hier
Die ersten, die mir in den Sinn kommen, sind drei Möglichkeiten, um dieses Problem zu lösen:
- Verwenden Sie Browser-Tools oder schreiben Sie Plugins für diese
- Organisieren Sie den Datenaustausch über das Backend und fungieren Sie als Vermittler
- Fügen Sie dem Programm einen HTTP-Dienst hinzu und greifen Sie direkt über den Browser darauf zu
Das dritte Element sieht gut aus, ermöglicht es Ihnen, die Autorisierung im Programm zu entfernen, erfordert überhaupt keine Benutzeroberfläche. Versuchen wir, es zu implementieren, indem Sie ein Programm in C # unter .NET Framework 4 schreiben. Da es sich um .NET handelt, ist die Lösung nur für Windows (XP und neuer) verfügbar. Wir werden die Webanwendung auf eckig machen.
Warum nicht 1 und 2?
Das erste Element wird definitiv viel Schmerz bringen, Sie müssen Browser separat unterstützen, Sie können weit von allem in Browser-Plug-Ins tun. Theoretisch ist es jedoch möglich, über Plugins mit Smartcards zu arbeiten. Aber Sie brauchen einen einfacheren Weg.
Der zweite Punkt ist einfach zu implementieren, aber für dieses Schema müssen Sie die Autorisierung nicht nur auf der Site, sondern auch in der lokalen Anwendung durchführen. Dies bedeutet, dass eine Art Schnittstelle erforderlich ist, aber beim Ändern des Kennworts ist auch eine erneute Autorisierung im Programm erforderlich. Außerdem treten in Unternehmensnetzwerken zusätzliche Probleme mit dem Netzwerk auf. Sie verfügen häufig über einen Internetzugang über Proxys mit schwerwiegenden Filtern und Berechtigungen. Außerdem müssen Sie eine Schnittstelle zum Konfigurieren von Proxys einrichten und automatische Einstellungen können nicht immer entfernt werden. Es wird für einen Benutzer, der weit von der IT entfernt ist, schwieriger sein, damit zu arbeiten, und wir werden mehr technischen Support schaffen. Natürlich können Sie für jeden Benutzer ein individuelles Installationspaket erstellen, um die Notwendigkeit einer primären Autorisierung zu beseitigen. Dies trägt jedoch nur zu den Problemen bei.
Was hat HTTPS damit zu tun?
Wenn eine Site über HTTPS ausgeführt wird, blockieren Browser den Download von aktivem Inhalt über HTTP. Gemäß der Logik der Dinge sollten Browser die Anforderung an den lokalen Computer über HTTP jedoch als sicher betrachten und sie nicht blockieren. Dies stellte sich als nicht ganz so heraus.
Die Tabelle zeigt die Ergebnisse einer kleinen Studie zum Verhalten von Browsern auf der Windows-Plattform:
Die Tabelle zeigt das Verhalten von Browsern beim Versuch, eine Anfrage an die entsprechende Adresse zu stellen. Browser auf der Chromium-Engine verhalten sich ähnlich wie Chrome, und das Verhalten von Edge 44 ähnelt dem Verhalten von IE 11. Für HTTPS wird ein gültiges Zertifikat ausgestellt, das mit einem selbstsignierten Stammzertifikat signiert ist. Das Verhalten für https://127.0.0.1 und https: // localhost ist das gleiche. Nur für 127.0.0.1 müssen Sie ebenfalls ein Zertifikat ausstellen, und Zertifikate für IP-Adressen werden selten gefunden. Daher wird dieser Punkt weggelassen.
Alles funktioniert in Chrome. Chrome und IE verwenden den Systemzertifikatsspeicher, sodass HTTPS auch in ihnen funktioniert. Firefox verwendet einen eigenen Zertifikatspeicher, daher vertraut es unserem selbstsignierten Zertifikat nicht. Firefox und IE vertrauen dem Namen des lokalen Hosts nicht, und das ist richtig, da niemand garantiert, dass er in 127.0.0.1 aufgelöst wird (obwohl sie ihn einfach wie Chrome überprüfen könnten).
Das Hauptproblem: IE erlaubt keinen Zugriff auf das Programm über HTTP. So viel Aufhebens um Zertifikate können wir nicht vermeiden.
Um mit Browsern arbeiten zu können, müssen Sie im Programm auch die richtigen CORS -Header (Access-Control-Allow-Origin, Access-Control-Allow-Methoden und Access-Control-Allow-Header) angeben.
SSL-Zertifikat
Sie können einen DNS-Eintrag für Ihre Domain erstellen, z. B. local.example.com, der in 127.0.0.1 aufgelöst wird. Stellen Sie ein SSL-Zertifikat für diese Domäne aus und verteilen Sie es mit dem Programm. Sie müssen den privaten Schlüssel dieses Zertifikats mit dem Programm verteilen. Dies ist völlig ungeeignet. Außerdem muss das Zertifikat im Programm aktualisiert werden.
IE vertraut einem selbstsignierten SSL-Zertifikat nicht, es muss mit einem vertrauenswürdigen Stammzertifikat signiert sein (und es kann selbstsigniert sein).
Sie können ein Stammzertifikat und ein SSL-Zertifikat generieren und diese mit dem Programm verteilen und zum lokalen Zertifikatspeicher hinzufügen. Es sieht unsicher aus. Möglicherweise muss das Zertifikat auch widerrufen oder erneuert werden. Daher generieren wir beim ersten Programmstart Zertifikate mit Schlüsseln direkt auf dem Computer des Benutzers.
Erstellen von Zertifikaten in C #
Für .NET gibt es eine BouncyCastle- Bibliothek, die alles kann, was wir brauchen. Das einzige Problem besteht darin, dass Sie zum Hinzufügen eines Zertifikats zum Geschäft eine Erhöhung der Berechtigungen beantragen müssen. Sie benötigen außerdem erhöhte Rechte, um mit netsh das Zertifikat an einem bestimmten Port im System zu sichern.
netsh http add sslcert ipport=0.0.0.0:{PORT} certhash={certThumbprint}
Im Beispiel führt die RegisterSslOnPort-Methode in der SslHelper-Klasse diesen Job aus.
HTTP-Dienst im C # -Programm
Um einen leichtgewichtigen HTTP (S) -Server zu erstellen, verwenden wir die Nancy-Bibliothek . Nancy ist ein leichtes Webframework für .NET, einfach und benutzerfreundlich. Es wurde viel über ihn geschrieben, auch über Habré . Dank des Nancy.SelfHosting-Moduls können wir unsere Anwendung ohne Verwendung von IIS hosten.
Erstellen wir beispielsweise einen Endpunkt, der sich mit der Addition von zwei Zahlen befasst. Hier ist es wichtig, die richtigen CORS-Header festzulegen, da der Browser sonst keine Anforderung an unsere API ausführt.
Nancymodule public class CalcNancyModule : NancyModule { public CalcNancyModule() {
Fügen Sie unserer Anwendung die Nancy-Initialisierung hinzu, und wir sind bereit für den Kampf.
Nancy Initialisierung var hostConfigs = new HostConfiguration(); hostConfigs.UrlReservations.CreateAutomatically = true; hostConfigs.RewriteLocalhost = false; var uris = new Uri[] { new Uri($"http://localhost:{HTTPPORT}"), new Uri($"http://127.0.0.1:{HTTPPORT}"), new Uri($"https://localhost:{HTTPSPORT}") }; using (var host = new NancyHost(hostConfigs, uris)) { host.Start(); }
Beim ersten Start müssen Sie Zertifikate generieren und im Geschäft ablegen, um die entsprechenden Rechte anzufordern. Die SslHelper-Klasse wird für diese Manipulationen verwendet, bei denen die einzige öffentliche CheckOrCreateCertificates-Methode den Job ausführt. Als Parameter werden SubjectName-Zertifikate an sie übergeben. Die Methode prüft, ob die erforderlichen Zertifikate verfügbar sind, und das System erstellt sie, falls nicht.
Fügen Sie unseren API-Aufrufen Thread.Sleep (1000) hinzu, um harte Arbeit und lange Verzögerungen im Beispiel zu simulieren.
Wenn diese Anwendung zur Ausführung bereit ist, gehen Sie ins Web.
Webanwendung
Wie Sie der Verhaltenstabelle des Browsers entnehmen können, kann auf einen Endpunkt nicht verzichtet werden. Es müssen mindestens zwei verwendet werden:
In einer Webanwendung müssen wir feststellen, ob wir uns im IE (oder Edge) befinden - verwenden Sie HTTPS, wenn nicht - HTTP. Sie können es zuverlässiger machen und nicht herausfinden, in welchem Browser wir uns befinden. Versuchen Sie einfach, eine Anforderung an die GET / Calc-Methode unserer API auszuführen. Wenn die Anforderung erfolgreich ist, arbeiten wir, wenn nicht, versuchen wir es mit einem anderen Protokoll.
All dies ist nur erforderlich, wenn die Webanwendung selbst HTTPS verwendet, da Browser bei Verwendung des HTTP-Protokolls keine Einschränkungen für Anforderungen auferlegen, sondern nur die richtigen CORS-Header benötigt werden.
Erstellen Sie in der Winkelanwendung einen InteractionService-Dienst, der die Verfügbarkeit des lokalen Endpunkts zuerst über HTTP und dann über HTTPS überprüft. Die Prüfung wird von der checkAvailability-Methode durchgeführt, und das Ergebnis der Prüfung ist verfügbar, wenn die verfügbare $ -Variable vom Typ BehaviorSubject mit dem Anfangswert false abonniert wird.
Wir fügen der AppComponent-Komponente die Arbeit des Hinzufügens von Zahlen hinzu. Wenn Sie auf die Schaltfläche "Berechnen" klicken, fordert die Webanwendung GET / Calc / Add? Num1 = {num1} & num2 = {num2} an. Die Antwort oder der Fehler wird im Feld Ergebnis angezeigt.
Beim Debuggen werden Sie möglicherweise auch über HTTPS keine Probleme bemerken, da die Domäne für Anforderungen dieselbe ist - localhost. Daher müssen Sie die Anwendung mit einem anderen Domänennamen testen.
Um die Bereitstellung einer Webanwendung so weit wie möglich zu vereinfachen, verwenden wir den Dienst https://stackblitz.com . Dies ist eine Web-IDE für Angular und nicht nur mit einem Hauch von VSCode. Die fertige Bewerbung finden Sie unter dem Link .
Und Sie können den Code hier graben .
Die Anwendung funktioniert nicht interaktiv auf stackblitz. Sie müssen sie in einem separaten privaten Tab oder in einem anderen Browser unter https://angular-pfwfrm.stackblitz.io öffnen.
Wie versuche ich es?
Die Webanwendung wird bequem mit stackblitz gestartet, indem Sie einfach auf den Link https://angular-pfwfrm.stackblitz.io klicken.
Sie können die Webanwendung lokal ausführen.
Dafür brauchst duDazu müssen Sie das Repository klonen:
git clone https://github.com/jdtcn/InteractionExample.git cd InteractionExample
Im AngularWebApp-Ordner müssen Sie die folgenden Befehle ausführen:
npm install ng serve --ssl true
Die Webanwendung ist unter https: // localhost: 4200 / verfügbar.
Die lokale Anwendung kann entweder mit Visual Studio aus dem Beispiel kompiliert werden (CsClientApp.sln aus dem CsClientApp-Ordner öffnen) und ausgeführt werden, oder das Skript für das LINQPad- Programm verwenden.
Wenn Sie ein .NET-Entwickler sind und LINQPad nicht verwenden, lesen Sie unbedingt darüber , was in der Entwicklung unverzichtbar ist. Um das Beispiel auszuführen, müssen Sie das Skript in LINQPad'e öffnen (das erste Mal, wenn Sie LINQPad mit Administratorrechten ausführen müssen, um die Zertifikate zu installieren) und die Nuget-Pakete BouncyCastle, Nancy, Nancy.Hosting.Self installieren und dann das Skript ausführen. Danach können Sie in der Webanwendung auf die Schaltfläche „Berechnen“ klicken und das Ergebnis des Vorgangs abrufen.
Sicherheit
Es ist wichtig, CORS-Header in einer realen Anwendung korrekt zu bilden, damit Bösewichte von anderen Websites nicht auf unser Programm zugreifen können. Wenn der Bösewicht die Möglichkeit hat, mit den Berechtigungen des Benutzers auf seinem Computer zu arbeiten und die CORS-Prüfung zu umgehen, kann er alles tun, was unser Programm kann.
In jedem Fall sollte das Programm mit minimalen Rechten arbeiten. Wenn es mit Dokumenten etwas Sensibles tut, müssen Sie ihm Anforderungen zur Bestätigung von Vorgängen hinzufügen.
Fazit
Die scheinbar einfache Aufgabe erwies sich als ziemlich umfangreich und erforderte sogar zusätzliche Krücken für die Arbeit mit Zertifikaten.
Dieser Ansatz hat sich in einer realen Anwendung bewährt. Um den Code aus dem Beispiel zu verwenden, müssen Sie natürlich eine normale Fehlerbehandlung hinzufügen.
Es ist praktisch, bei der Installation des Programms die Erhöhung von Berechtigungen anzufordern. Mit InnoSetup ist dies einfach und übergeben Sie das erforderliche Attribut beim ersten Ausführen des Programms. Vor der Installation sollten Sie außerdem prüfen, ob .NET 4 vorhanden ist, und es installieren, wenn es nicht installiert ist.
Niemand bei Virustotal reagiert auf dieses Programm, aber ich würde gerne! Wenn Sie jedoch das Installationspaket in InnoSetup zusammenstellen, arbeiten einige Antivirenprogramme der dritten Klasse daran. Dies hilft dabei, die Signatur des Installationsprogramms mit dem Codesignaturzertifikat zu beseitigen.
Das automatische Update des Programms hier ist hinter den Kulissen, aber es wird in einer realen Anwendung sicherlich nicht überflüssig sein. Eichhörnchen eignet sich gut zum Verwalten von automatischen Updates. Es ist auch praktisch, Eichhörnchen zu verwenden, um unsere Zertifikate aus dem System zu entfernen, wenn Sie das Programm löschen.
Beispielcode auf GitHub .
Vielen Dank für Ihre Aufmerksamkeit!