Nützliche Webseiten zur Analyse von DNS-Problemen mit gehosteten Web-Domainen

Gestern rief meine Frau an, die sich z.Z. bei Bekannten in Norwegen aufhält; Firefox würde eine von ihr betreute norwegische Homepage eines Kunden nicht mehr anzeigen – weder auf dem Windows-Desktop noch auf ihrem Mobil-Telefon. Bei einem Kollegen ginge es aber anstandslos. Andere Webseiten konnte sie problemlos aufrufen; nur eben nicht die Seiten der von ihr betreuten norwegischen Web-Domaine.

Das sind so Themen, die einen durchaus eine Weile beschäftigen können, da in einer solchen Situation potentiell mehrere Provider ins Spiel kommen. Da ist einerseits mal der Internet-Provider der Verwandtschaft in Norwegen; über den erhält der dortige Router in der Standardkonfiguration automatisch DNS-Server-Adressen zugewiesen. Der Kunde hingegen hatte seinen Web-Space bei einem sog. “norwegischen Web-Hotel” – also bei einem kleineren norwegischen Web-Server-Provider – gehostet. (Der Vertrag ist außerhalb von unserer Verantwortung und Beratung geschlossen worden).

Natürlich war hinter der ganzen Angelegenheit ein DNS-Problem zu vermuten. Allerdings war auch klar, dass das ein etwas ungewöhnliches Problem sein musste, da es nur domain-spezifisch auftrat. Ich beschreibe nachfolgend kurz das Vorgehen zur Analyse mit Hilfe von im Internet verfügbaren Diensten und einiger nützlicher Webseiten. Das Ergebnis war für mich zudem etwas überraschend; man lernt ja nie aus.

Zunächst ließ ich checken, welche DNS-Server dem Router in Norwegen zugeordnet waren; dann, ob diese Server überhaupt ihren Dienst taten. Letzteren Schritt konnte ich nicht von Deutschland aus mit einem der üblichen Linux-Kommandos “dig”, “host” oder dem alten “nslookup” erledigen. Grund: Der Provider verweigert den Zugriff auf seinen DNS-Server aus dem Ausland.
Also musste meine Frau die Windows-Variante von “nslookup” in der MS Windows Eingabe-Aufforderung benutzen. (Die Syntax – s. “nslookup /?” – ist sehr linux-ähnlich). Ergebnis: Die DNS-Server des Providers funktionierten zwar, konnten den Namen der Problem-Domaine aber tatsächlich nicht in eine IP-Adresse auflösen – andere Domainnamen hingegen schon.

Ein Gegentest mit verschiedenen anderen, öffentlich zugänglich DNS-Servern in Norwegen (http://public-dns.info/nameserver/no.html) ergab dann, dass einige dieser DNS-Server die Namensauflösung vornahmen, einige wenige aber nicht.

Für andere Länder findet man öffentlich zugängliche DNS-Server übrigens mit

http://public-dns.info/nameserver/LANDESKUERZEL.html

Ein ähnliches Ergebnis lieferte dann eine Stichprobe für deutsche DNS-Server: die allermeisten DNS-Server führten die Namensauflösung für die betroffene norwegische Web-Domaine durch, einige aber auch hierzulande nicht. Dadurch misstrauisch geworden, überprüfte ich als nächstes, was denn die Datenkrake Google zu der ganzen Sache meinte.

So kann man beispielsweise mal

host xyz.no 8.8.8.8 oder host xyz.no 8.8.4.4

ausführen (xyz ist natürlich durch den korrekten Domainnamen zu ersetzen). die IP-Adressen entsprechen öffentlichen DNS-Servern von Google.

Und siehe da – auch Google verweigerte die Namensauflösung mit der Meldung “SERVFAIL”; das Ergebnis erhielt ich natürlich auch über https://dns.google.com.

Interessant – aber ein Seitenaspekt – ist in einer solchen Situation auch, wie eigentlich eine Domaine nach außen im Internet erscheint, wer darauf verlinkt und ob die zugeordnete IP von mehreren anderen Web-Domainen geteilt wird. Hierzu kann man mal einen Blick auf den Web-Dienst

http://domainstats.io/

werfen und dort seinen Domainnamen eingeben (oder gleich http://domainstats.io/domainname). Man erhält dann in der Mitte der Seite mit vielen Analyse-Ergebnissen auch eine Info zur IP – und wie oft die geteilt wird.
Ein Klick auf die Zahl oder aber die Eingabe von

http://domainstats.io/IP-ADRESSE

in der HTTP-Adresszeile des Browsers liefert dann mehr und übersichtliche Informationen über die Web-Domainen zur gleichen IP-Adresse.

Für uns interessant war das Ergebnis trotz keiner direkten DNS-bezogenen Auskunft trotzdem. Denn auf diesem Wege erfuhren wir, dass die betreute Domaine (inzwischen?) auf einem US-amerikanischen Server gehostet und dass die Web-Server-IP mit 48 anderen Domainen (meist norwegische Domainen) geteilt wird. Davon wusste weder unser Kunde etwas, noch bislang wir.

Im Klartext: Der Web-Hoster in Norwegen kooperiert offenbar mit einem amerikanischen Provider – und nutzt dessen Hosting-Dienste – wohl um selbst Kosten zu sparen. Inkl. der an die Domaine angeschlossene Mail-Dienste. Ohne allerdings den Kunden über dieses Faktum zu informieren …

Off Topic: Dass in den USA ein anderer Datenschutz gehandhabt wird als in der EU ist wohl auch Norwegern inzwischen bekannt … Aber, was solls, Norwegen ist ja selbst auch nicht in der EU und sein Geheimdienst betreibt angeblich auch Supercomputeranlagen zur Dechiffrierung kryptierter Information
http://www.golem.de/news/spionage-supercomputer-soll-norwegen-beim-entschluesseln-helfen-1404-106115.html
http://www.spiegel.de/netzwelt/web/steelwinter-supercomputer-norwegens-geheimdienst-kooperiert-mit-nsa-a-966541.html
https://netzpolitik.org/2014/steelwinter-nsa-verkauft-supercomputer-an-norwegischen-geheimdienst/
Unabhängig davon gilt wohl: Augen auf bei der Provider-Wahl für Web-Hosting in Norwegen …. Man sollte sich als Betroffener vorab informieren, wo die eigenen Daten letztlich wirklich gehostet werden – und dann entscheiden, ob man das für gut hält …

Nun war es endgültig an der Zeit, sich darüber zu informieren, aus welchen Gründen es z.B. bei Google Probleme mit der Namensauflösung geben kann. Weiter half dabei die Seite
https://developers.google.com/speed/public-dns/docs/troubleshooting
Sie liefert einige nützliche Informationen und verweist auf weitere Seiten, die eine übersichtliche Analyse der DNS-Situation für eine Web-Domaine liefern können; für eine solche Analyse müsste man auch als Linuxer einigen Aufwand betreiben und sich viele Optionen der Kommandos nslookup, dig, host zu eigen machen :

http://intodns.com/

Das dortige Toolset analysiert zwar nur Haupt- und keine Sub-Domainen; das reicht ja aber in der Regel. Ich kann jedem nur raten, sich das ausführliche Ergebnis mal für die eigene Domainen anzusehen und über evtl. monierte Punkte nachzudenken und diesbzgl. auch ggf. seinen Provider zu kontaktieren.

Interessant war auch im Fall des norwegischen Hosters wieder eine Abweichung von deutschen Gepflogenheiten festzustellen – hierzulande werden zumindest bei den großen Providern die autoritativen DNS-Nameserver zu einer .de-Domaine in getrennten Netz-Segmenten und unabhängig von den Web-Servern betrieben. Eine Zusammenstellung der Anforderungen (im Jahr 2012) findet man z.B. hier
http://www.inmotionhosting.com/support/community-support/dns-nameserver-changes/nameserver-requirements-to-de-domain-name,
http://manage.resellerclub.com/kb/
answer/1132
,
https://de.godaddy.com/help/about-de-domains-5825.
Der TÜV stellt im Rahmen von Firmenzertifizierungen noch weitergehende Anforderungen wie z.B. echte unabhängige Internet-Uplinks etc.. Im Falle des norwegischen (besser amerikanischen Hosters war ein Nameserver mit dem Webserver identisch. Ein zweiter lag im selben C-Segment.

In Norwegen ist übrigens die Organisation NORID für die übergeordneten Domain-Services zuständig. Allerdings erfährt man aus den “whois”-Einträgen anders als bei der DENIC nicht direkt die IP-Adressen der autoritativen Name-Server für eine Domaine. Hier helfen auf die Schnell die Informationen von intodns.com. Oder:

host -C domain-name

Es lohnt sich generell, mal die man-Seiten zu nslookup, host und dig bzgl. der möglichen Optionen zu scannen.

Im Falle unserer norwegischen Problem-Domaine spuckte intodns.com zwar einige kleinere Warnhinweise aus – nichts davon erschien mir aber die fehlende Namensauflösung erklären zu können. Aber Google weist ja freundlicherweise auch auf

http://dnsviz.net/

hin. Die dortigen DNS-Tools untersuchen die Einhaltung von DNSSEC-Standards. Es geht dabei um die Signierung von DNS-Informationen mit Hilfe kryptografischer Schlüssel und Zertifikate. Siehe für eine Kurzdarstellung:
https://de.wikipedia.org/wiki/Domain_Name_System_Security_Extensions

Eine wesentlich ausführlichere und gute Einführung liefert folgender Artikel von U. Wisse, der unter den Webseiten von Heise publiziert wurde :
http://www.heise.de/netze/artikel/Domain-Name-System-absichern-mit-DNSSEC-903318.html

Nachvollziehbare Kritik zum DNSSEC-Verfahren findet man z.B. hier:
http://www.golem.de/news/imho-dnssec-ist-gescheitert-1506-114940.html

Interessant finde ich, dass das ganze DNSSEC-System allein von US-amerikanischen Root-Zonen-Servern und der dortigen DNSSEC-Schlüssel-, genauer Zertifikats-Verwaltung abhängig ist. Als neutrale Verfikationsinstanz für die Zertifikatsechtheit fungiert wiederum ein amerikanisches Unternehmen. Das aber nur nebenbei …

Der Einführung von Hrn. Wisser entnimmt man, dass schon kleine Fehler beim Aufsetzen der DNSSEC-Informationen auf DNS-Servern, die DNSSEC unterstützen, zur Nicht-Erreichbarkeit einer Web-Domaine führen können. Das Gleiche gilt, wenn Umzüge von Domainen zu Providern stattfinden, die z.B. DNSSEC nicht unterstützen – der originale Provider aber auf seinen Servern noch DNSSEC-Einträge vorhält. Darauf weist auch die oben genannte Google-Seite hin.

Tja, was soll ich noch mehr sagen: “http://dnsviz.net/” lieferte gestern substanzielle Fehler bzgl. der verfügbaren DNSSEC Information zu unserer Problem-Domaine. Kein Wunder, dass Google und andere DNSSEC-fähige DNS-Server die Namensauflösung verweigerten. Viele andere DNS-Server prüfen DNSSEC-Information übrigens nicht – was einen Teil des obigen Befunds erklärt.

Der norwegische Hosting-Provider unseres Kunden hat inzwischen auf seinen Webseiten zugegeben, dass für einige “Konten” Fehler beim Update von DNSSEC-Informationen aufgetreten seien. Die würden behoben. Tatsächlich liefert dnsviz heute keine Fehler mehr. Der irritierte Kunde ist jetzt auch wieder glücklich – ich habe nebenbei etwas über DNSSEC gelernt – und auch darüber, wie sehr der Betrieb von DNSSEC von Amerika abhängig ist. Gelernt habe ich ferner, dass DNS-Probleme durch DNSSEC-Fehlern von Hosting-Providern verursacht sein können.

Dass Provider wiederum Provider nutzen, ist dagegen keine neue Erkenntnis. Dass Hosting-
Provider in Nicht-EU-Ländern gehostete Websites aber auf Server in ein anderes Land – hier: die USA – verschieben, ohne dass der Kunde etwas davon erfährt, war ein anderes interessantes Lehrstück. Ich hoffe, derlei ist in Deutschland unmöglich.

Ansonsten: Viel Spaß beim Anwenden der oben angegebenen Analyseseiten auf die von euch betreuten Web-Domainen.

P.S.: DNS-Analysen im Rahmen von Penetrationstests
Wer sich mehr für DNS-Analysen z.B. im Rahmen von Penetrationstests interessiert, sollte auch mal einen Blick auf folgende Seite werfen: http://resources.infosecinstitute.com/dns-hacking/
Auch “dnsrecon” und “dnsenum” sind interessante Tools, die in Penetrationstests aber mit Bedacht eingesetzt werden muss (s. https://w3dt.net/tools/dnsrecon). Brute Force-Einsätze sind zu unterlassen, wenn keine entsprechenden Einwilligungen des Netzbetreibers vorliegen.

Windows 10 und die Süddeutsche Zeitung

Man würde meinen, dass die Technik-Sparte einer seriösen Zeitung wie der SZ von Journalisten gestaltet wird, die die Kunst der kritischen Distanzwahrung und der sachlichen Informationsweitergabe zu kontroversen Themen gelernt haben. Oder im Zweifel zumindest Fachleute (!) mit unterschiedlichen, aber begründeten Ansichten zu einem kontroversen Thema zu Wort kommen lassen.

Hrn. Hurtz von der SZ hat es heute mit seinem Artikel
“Heute noch geschenkt, bald richtig teuer”
(http://www.sueddeutsche.de/wirtschaft/windows-betriebssystem-heute-noch-geschenkt-bald-richtig-teuer-1.3095229)
zur kommenden Kostenpflichtigkeit von Windows 10 geschafft, technischen Journalismus in ungeahnte Tiefen zu führen. Und er hat den erreichten Tiefpunkt dann nochmal durch einen nachgeschobenen Online-Artikel
http://www.sueddeutsche.de/digital/microsoft-warum-sie-keine-angst-vor-windows-haben-muessen-1.2835023
tiefer gelegt.

Ich habe die genannten Artikel gleich dreimal lesen müssen, weil man es ja kaum für möglich hält, wie distanzlos sich die SZ – hoffentlich ungewollt – vor den Karren der Interessen Microsofts spannen lässt. Ich persönlich halte bekanntermaßen wenig von MS-PC-Produkten – das ist eine, nämlich meine Sache. Aber Artikel, in der die Presse in fast humorigem Ton die Werbe-Arbeit von MS verrichtet, ist eine andere. Ich erlaube mir, in diesem Fall ein großes Fragezeichen hinter die Seriosität der genannten Artikel und hinter die interne Qualitätssicherung bei der SZ zu setzen. Ehrlich, die Lektüre ist mir aufs Gemüt geschlagen – ich hätte es nicht für möglich gehalten, dass die SZ so was publiziert. Der Frust macht ein wenig Polemik zur erneuten Gewinnung des inneren Gleichgewichts fast unerlässlich. Wohlgemerkt, mir geht es dabei gar nicht um Microsoft. Das vertritt wie jedes Unternehmen legitimerweise seine Interessen – und Windows 10 interessiert mich nun wirklich nur peripher. Mir geht es darum, wie abgrundtief schlecht die obigen Artikel sind.

Welche neutrale Sachinformationen liefert uns der erste der genannten Artikel, der sich in der heutigen Druckausgabe der SZ über 5 Spalten erstreckt und vom nicht bebilderten Teil der Seite etwa die Hälfte einnimmt? Genau zwei: Windows 10 wird ab August etwas kosten. Und MS hat das eigene Ziel von 1 Milliarde Upgrades bislang weit verfehlt. Das war’s. Dafür würde man wohl kaum 5 Spalten brauchen. Nun könnte sich an die Sachinformationen ja z.B. eine Gegenüberstellung begründeter (!) Argumente für und gegen ein Upgrade von Windows 10 anschließen. Aber was lesen wir?

Da ist zunächst wortgewaltig von “religiösem Eifer” und “Glaubenskriegen” der Gegner von Windows 10 die Rede. Wir erfahren unter Zuhilfenahme eines Zitats von Umberto Ecco von 1994 (!), dass die IT-Welt schon immer in 2, seit kurzem aber sogar 3 religiöse Lager geteilt sei: Apple-Anhänger, Windows 10- und Windows 7-Anhänger. Dass die schärfste Kritik an Windows 10 möglicherweise gar nicht von Apple- oder Windows 7 Anhängern kommt, muss man sich als Leser erst viel später aus der beiläufigen Erwähnung von Klagen deutscher Verbraucherschutz-Verbände erschließen.

Der Rest des verfügbaren Platzes wird durch die Wiedergabe von Einschätzungen des Leiters des Geschäftsbereichs für Windows von MS Deutschland zur Kritik an Win 10 in Anspruch genommen. Von diesem Herrn erfahren wir dann lang und breit, welche wenig stichhaltige Argumente die Windows 10 Gegner (angeblich) ins Feld führen – etwa “never touch a running system” (gemeint ist Windows 7). Das sitzt … ich reibe mir die Augen und bin echt betroffen. So hatte ich das Thema Windows 10 zwar noch nie gesehen; aber wenn ein Geschäftsführer von MS das sagt ….. Richtig beeindruckend, diese
saubere, gründliche Journalistenarbeit von der SZ ….

Und dann wird es wirklich interessant – es geht um “Die beiden zentralen Kritikpunkte an Windows 10 – Datenschutzbedenken und Zwangsupgrade”. Na, was erfahren wir wohl dazu? Ja, die halte der Leiter des Windows-Geschäftsbereichs Deutschland für “überschätzt”. Ach wirklich? Echt ???… das hätte ich nun überhaupt nicht erwartet…. Der journalistische Tiefgang des Artikels, der das alles kommentarlos weitergibt, beeindruckt mich immer mehr …

Und weiter: Wer wolle, könne ja die “meisten Überwachungsfunktionen abschalten”. usw., usw.. “Und was viele Nutzer als penetrante Aufforderung zum Upgrade empfunden haben” hält der Geschäftsführer von MS für ein vernünftiges Vorgehen. “Niemand sei … zwangsbeglückt worden”. Diese Botschaft freut sicher jeden, der mal versucht hat, die “Beglückung” durch Werkeln in der Wndows-Registry abzuschalten.

Die journalistische Meisterleistung von Hrn. Hurtz wird abschließend von der Wiederholung seiner Erkenntnis gekrönt, dass sich die Tech-Szene in Kürze in drei “Religionen” (Apple, Win 10, Win 7) teilen werde. Halt – da entdeckt der SZ-Journalist doch noch eine weitere Gruppe – nämlich die “Atheisten” – ja, liebe Leute, das sind wir, die mit Linux.

Wem der Salat an MS-Meinungswiedergabe als Haupt-“Information” des Artikels noch nicht gereicht hat, der konnte ergänzend einen 2-spaltigen Kasten mit Kleingedrucktem lesen, in dem die schöne neue Welt von Windows angepriesen wird: Nur noch laufende Updates eines ewigen Windows 10 und verbesserte Funktionen “eines bereits stimmigen Betriebssystems”. Ja, wer’s mag – wie offenbar besagter Redakteur der SZ – für den ist das halt das Höchste ..

In dieser begrenzten Logik bleibt die (IT-) Erde auch weiterhin eine Scheibe … sie wird in Zukunft nur viel runder und noch stimmiger. Never touch a running ideology … die religiösen Eiferer aus dem Apple und Win 7-Lager und wir, die “Atheisten” aus dem Linux-Lager, haben da nur noch nicht genau genug hingesehen. Der Abgrund am Rand der Scheibe ist jetzt dank ausführlicher Nutzungsklauseln sogar markiert und mit dem verbesserten Angebot kann man noch tiefer in ihn hineinsehen – kein Grund mehr ihn zu überschätzen … Danke, liebe SZ, für diese humorig verfasste “Information” – endlich habe ich es begriffen! Bleibt nur die Frage, warum Hr. Hurtz nicht einfach, kurz und prägnant geschrieben hat:

Liebe MS-Gläubigen, die ihr bisher der täglichen frohen Upgrade-Botschaft aus völlig unverständlichen bis ketzerischen Gründen nicht gefolgt seid: Beeilt euch mal – denn sonst muss MS den Klingelbeutel in der Gemeinde rumgehen lassen. Und wie wir aus gewöhnlich bestens informierten Kreisen der MS-Geschäftsführung erfahren haben, sind alle eure Motive, Windows 10 nicht einzusetzen, in der Nähe religiösen Eifertums angesiedelt, aber objektiv nicht nachvollziehbar. Die MS-Geschäftsführung weiß das – und natürlich auch, was wirklich gut für euch ist !! Ihr müsst es einfach nur glauben. Und Datenschutz in Europa und Deutschland ist ja eh’ schon immer überschätzt worden. Nun aber bitte gleich upgraden – damit MS seine Geschäftsziele erreicht. Sonst Strafgebühr ….

Das wäre wenigstens klar, ehrlich und platzsparend gewesen – und man müsste sich als Leser nach der Lektüre nicht verzweifelt die Frage stellen, ob Hr. Hurtz in seinem aufklärerischen Eifer schlicht nicht gemerkt hat, dass dieser Artikel auch aus der Werbeabteilung Microsofts stammen könnte. Bis 15:00 Uhr habe ich noch an Unbedarftheit geglaubt; aber dann wird von der SZ online noch ein weiterer Artikel nachgeschoben mit dem Titel: “Warum Sie keine Angst vor Windows 10 haben müssen”.

Einige Argumente werden auch in diesem Artikel wieder aus dem reichen Erkenntnisschatz von MS geliefert: Das Datenabgreifen erfolge ja im besten Interesse des Nutzers und würde nur in anonyme Statistiken einfließen. Wer die Nutzungsbedingungen ganz lese (was aber wegen der
Länge kaum einer tue) könne das begreifen. Und MS würde nie persönliche Mails durchsuchen, um Werbung zu schalten. Sagt MS – und dann wird es ja wohl stimmen und muss von der SZ unreflektiert verbreitet werden. Offen bleibt in diesem einseitigen Diskurs die Frage der Ketzer: Aber warum werden z.B. die Mails der Windows 10 User dann überhaupt auf MS-Server übertragen?

Ich selbst habe alle Nutzungsbedingungen von MS Win 10 sehr genau gelesen – auch das flankierende Service Agreement: Da bleiben eigentlich keine Fragen offen. Du akzeptierst als Nutzer, dass MS bei Standardeinstellungen und im Zweifel zu Wartungszwecken alle deine Daten auf eigene Server transferiert. Wozu? Tja, da muss der MS-Adept halt einfach glauben, dass das zu seinem Wohle ist. Zu platt? Stimmt, denn selbst Hrn. Hurtz kommt dann auf Seite 2 des Artikels der schlimme Verdacht, das selbst die bislang Gläubigen nicht so einfach von neuen Götzen zu überzeugen sein werden. Und die Predigt nimmt dann eine neue Richtung:

“Komfort gibt es nur im Tausch gegen Privatsphäre …jeder Zugewinn an Komfort geht mit einem kleinen Verlust an Privatsphäre einher. Das ist bei Google und Apple aber nicht anders.” Denn: Das mit dem Komfort funktioniert nur – Zitat – “wenn man bereit ist, einen Teil seiner Privatsphäre zu opfern. Es gibt gute Gründe, diese Entwicklung zu bedauern. Aber es gibt keinen guten Grund, allein Microsoft an den Pranger zu stellen, weil sie mit der Zeit gehen. Wer diesen Weg nicht mitgehen will, hat längst eine gute Alternative zu Windows und iOS. Sie heißt Linux.

Aha, Überraschung: Privatsphäre geht bei Einsatz von Windows 10 womöglich doch verloren – aber ich soll MS halt glauben, dass das zu meinem Besten ist. Und dass andere Anbieter von PC- und Smartphone -Betriebs-Systemen auch nicht besser sind, ist dabei ein wirklich tröstlicher und tiefer Gedanke von Hrn. Hurtz. Habt keine Angst, liebe Gläubigen …in den Paradiesen der zukünftigen IT werden wir alle gleich unfrei sein.

Der Artikel erteilt dann abschließend noch die Absolution für die Ketzer; moderne Botschafter von Betriebssystem-Religionen sind schließlich liberal. Denn wer die beschriebene Opferung der informationellen Selbstbestimmung auf dem Altar des Dogmas “Komfort hat den Preis der Privatsphäre” partout nicht einsehen wolle, könne sich ja (ganz im Sinne des ersten Artikels) als Atheist aus den genannten drei Kirchen abmelden – durch die Benutzung von Linux. Letzteres muss gemäß der Hurtz’schen Argumentation und Logik aber leider höllisch unkomfortabel sein.

Na dann, liebe Linuxer – auf ins Fegefeuer … da muss man wenigstens keinen miserablen Journalismus mehr ertragen …

jQuery: Aufruf von Objekt-Methoden im Rahmen der Event-Behandlung und der .each()-Funktion für Selektionen

Will man Funktionalitäten, die man in Javascript/jQuery-Projekten erfolgreich entwickelt hat, wiederverwenden, muss man modular arbeiten und seine Funktionen in übergeordneten Einheiten kapseln. Wie einige meiner Leser wissen, versuche ich diese Anforderungen u.a. über die Etablierung abstrakter Control-Objects [CtrlOs] und definierte “Methoden” solcher Objekte umzusetzen.

Einerseits können Konstruktorfunktionen für abstrakte CtrlOs über ihren “prototype” zusammenhängende funktionale Verfahren im Sinne einer reinen Funktionalklasse bündeln.
Anderseits repräsentieren CtrlOs in meinen Web-Projekten bei Bedarf aber auch zusammenhängende Web-Bereiche sowie deren konkrete HTML-Objekte. Sie bündeln dann alle erforderlichen Methoden zum Umgang mit Ereignissen auf diesen Objekten. CtrlOs abstrahieren dabei soweit als möglich von der konkreten HTML-Ausprägung und führen zu einer allgemeineren Repräsentation bestimmter HTML-Schlüssel-Objekte im JS-Code – wenn nötig über die Definition weiterer geeigneter Unter-Objekte des CtrlOs. Wiederverwendbarkeit reduziert sich dann meist auf ein geeignetes Matching der IDs von Schlüsselelementen sowie ein Matching von Selektionskriterien für einen neuen Anwendungskontext (sprich für eine andere Webseite).

Beispiele:
Für die Steuerung einer Bildgalerie auf unterschiedlichen Webseiten ist z.B. lediglich der übergeordnete Container für die Bilder zu bestimmen und es sind geeignete Kriterien zur jQuery-Selektion der beinhalteten Bilder über Parameter zu definieren. Und schon können die meisten vordefinierten Methoden des CtrlOs wieder zum Einsatz kommen. Ein anderes Beispiel würde etwa die Kontrolle der Ajax-Interaktionen eines normierten Form-Elements mit einem PHP-Server zur Durchführung und Statusüberwachung eines Dateiuploads bieten. Auch hier lassen sich alle Funktionalitäten in Methoden eines relativ abstrakten und wiederverwendbaren CtrlOs bündeln.

Unter “Methoden” verstehe ich dabei allgemeine Funktionsobjekte, die als Elemente der fundamentalen “prototype”-Eigenschaft der Konstruktor-Funktionen für das CtrlO und ggf. der Konstruktorfunktionen für Sub-Objekte des CtrlO definiert werden. (In Javascript stellen Funktionen Objekte dar.)

Ziel ist es also, die gesamte Event-Behandlung und auch andere Aufgaben vollständig über “Methoden” eines für die jeweilige Aufgabe “fachlich” zuständigen CtrlOs und eventueller passend definierter Unterobjekte abzuwickeln. Das CtrlO entspricht somit einem (Singleton-) Container, der die Funktionalität zur Abwicklung aller auftretenden Ereignisse und Aufgaben in geordneter und wiederverwendbarer Weise kapselt. (Über den “prototype”-Mechanismus lässt sich dann natürlich auch eine “Vererbung” in komplexeren Projekten realisieren.)

Nun ist jQuery ursprünglich nicht auf eine solche Logik ausgerichtet; es sind daher ein paar Klimmzüge erforderlich, um HTML-Objekte einer Webseite mit Methoden abstrakter JS-Objekte zu koppeln. Vor allem der this-Operator und sein unter jQuery oftmals wechselnder Kontext führen dabei immer wieder zu Missverständnissen und Kapriolen.

So lenken jQuery’s Event-Behandlungs-Funktionen, die für jQuery-Objekte (Selektionen) ausgeführt werden, den this-Kontext in den aufgerufenen Callback-Funktionen auf das jeweilige HTML-Element um. Sind die Callbacks nun Methoden eines CtrlO-Objekts, so passt dies meist nicht zu der Erwartung, die den Entwickler beim Methoden-Design geleitet haben dürfte – nämlich, dass this in der Methode auf das CtrlO-Objekt selbst verweist.

Ich werfe daher zunächst einen Blick auf den $.proxy()-Mechanismus, der einem unter jQuery zumindest im Fall des Event-Handlings hilft, die erforderlichen Aufgaben an CtrlO-Methoden zu delegieren und den Kontext des this-Operators gezielt auf das CtrlO selbst zu setzen.

Danach wende ich mich einer Frage zu, mit der man es auch immer wieder zu tun bekommt:

Wenn man innerhalb einer CtrlO-Methode über eine Selektion von HTML-Objekten mittels der jQuery-Objekt-Funktion $(..).each( …) iteriert – wie delegiert man dann die anstehenden Aufgaben zur Behandlung der selektierten HTML-Objekte an eine (andere) geeignete “Methode” des abstrakten CtrlOs?
Und wie nutzt man dabei den this-Operator, so dass wir einerseits eine Referenz auf das CtrlO selbst und andererseits aber auch eine Referenz auf das aktuell zu behandelnde HTML-Objekt erhalten?

Wir werden sehen, dass sich der Aufruf der gewünschten CtrlO-Methode nicht ganz so bequem wie im Falle der Event-Behandlung über den $.proxy()-Mechanismus bewerkstelligen lässt; wir werden aber auch sehen, dass ein solcher Aufruf über einen kleinen Trick durchaus auf einfache Weise und ohne Informationsverlust möglich ist.

CtrlOs und Einsatz des $.proxy()-Verfahrens zur Delegation der Event-Behandlung an Objekt-Methoden bei gleichzeitiger Kontrolle des this-Operators

Das Abfangen von Events und die anschließende Delegation der funktionalen Bearbeitung an Methoden eines CtrlOs kann man relativ bequem über den $.proxy()-Mechanismus erledigen. Man registriert dazu im Rahmen der Definition der Event-Behandlung mittels geeigneter jQuery-Objekt-Funktionen (wie etwa “click()” ) die Funktion $.proxy() als primären Callback der Event-Behandlungs-Funktion – also z.B. click( $.proxy(), …). Der Funktion $.proxy() selbst wird dann einerseits eine Kontext-Referenz und eine Methode des CtrlO zur Event-Behandlung als Callback übergeben. Diese Verschachtelung von Callbacks hört sich kompliziert an – sie ist faktisch aber sehr bequem. Der Ansatz führt typischerweise zu Code-Abschnitten der unten angegebenen Art.

Voraussetzungen: GOC (“Global Object Controller”) definiert im Beispiel ein globales Objekt; um ein Zumüllen des globalen Kontextes zu vermeiden, werden die benötigten CtrlOs im GOC erzeugt. Wir nehmen für unser Beispiel vereinfachend an, dass die IDs benötigter HTML-Elemente über irgendwelche Parameter ermittelbar sind.


GOC = new Constr_GOC(); 

function Constr_GOC() {
    ....	
    this["CtrlO_Form"] = new Constr_CtrlO_Form( ...parameterS ...); 
    ....
    this["CtrlO_Form"].register_form_events(); 
    ...
}

//  Constructor of a CtrlO for a certain form-Tag  
// -----------------------------------------------
function Constr_CtrlO_Form(... parameters ...) {
    ....
    // gather or define concrete IDs of relevant HTML-objects 
    // by some appropriate evaluation methods
  
    this.id_form     = "#" + " ... (evaluation of parameters) ..."; 	
    this.id_rad_stat = "#" + ...; 	
    this.id_rad_heur = "#" + ...;
    this.id_but_chk  = "#" + ...;
    .....
    ....
}

// Proxy solution to register event handlers for HTML-elements   
// -----------------------------------------------------------
// The behaviour of the HTML-elements shall be controlled by CtrlO-methods 

Constr_CtrlO_Form.prototype.register_form_events = function() {
	
	console.log("From Form - registering event handlers for some key elements of the form");
		
	// Click on any of the radio buttons
	// ----------------------------------
       	$(this.id_rad_stat).click(
       	    jQuery.proxy(this, 'radio_click')
      	);
        $(this.id_rad_heur).click(
            jQuery.proxy(this, 'radio_click')
        );
        $(this.id_rad_both).click(
            jQuery.proxy(this, 'radio_click')
        );
			
	// Button_Click 
	// ----------------
	$(this.id_but_chk).click(
	    jQuery.proxy(this, 'click_event')
	); 
		
	// Submit Event 
	// ------------
	$(this.id_form).submit(
	    jQuery.proxy(this, 'submit_ajax_chkfiles')
	); 
			
};	

// 
Methods of the CtrlO 
// ------------------------------- 
Constr_CtrlO_Form.prototype.radio_click = function(e) {
    .....
    e.preventDefault(); 
    // get the JS-pointer to the HTML-Object for which the event e was triggered   	
    var pointerToHtmlObject = e.target;  	
    ....
    // var attribute = $(pointerToHtmlObject).attr(.....); 
    ....	
}
Constr_CtrlO_Form.prototype.click_event = function(e) {
    ....
}
Constr_CtrlO_Form.prototype.submit_ajax_chkfiles = function(e) {
    ...
}

 
Zuerst werden die IDs relevanter HTML-Schlüssel-Objekte anhand verfahrensspezifischer Kriterien identifiziert. Dann werden Event-Listener und -Handler für diese HTML-Objekte über geeignete jQuery-Funktionen registriert. Die Callbacks ‘radio_click’, ‘click_event’, ‘submit_ajax_chkfiles’ entsprechen im Beispiel Methoden, die über den prototype der Konstruktorfunktion für das instanziierte CtrlO bereitgestellt werden. Der this-Parameter, der an die $.proxy()-Funktion übergeben wurde, weist dabei auf das Objekt “CtrlO_Form” – dieses wiederum ist ein Element des GOC.

Der Aufruf von Callbacks als Event-Handler über jQuery-Objekt-Funktionen wie “.click()” führt dazu, dass der this-Operator innerhalb der im Eventfall ausgelösten Funktion auf das HTML-Objekt (!) verweist. Dies gilt auch, wenn der Callback eine Objektmethode sein sollte. jQuery setzt intern den Kontext für den this-Operator in expliziter Weise! Das führt regelmäßig zur Problemen, da ein Entwickler bei der Ausformulierung von Methoden als Teil des “prototype” eines Konstruktors in der Regel erwartet, dass this auf das (später) erzeugte Objekt zeigen wird.

Das Zwischenschalten der $.proxy()-Funktion sorgt im obigen Beispiel deshalb dafür, dass die jeweils genannte Methode zur Eventbehandlung aufgerufen wird und dass der this-Operator innerhalb der aufgerufenen Methode (wie erwartet) auf das CtrlO und nicht auf das HTML-Objekt zeigt, für das der Event ausgelöst wurde.

Wie aber erhält man nun in der CtrlO-Methode einen Zeiger auf das HTML-Object? Nun dies ist über das Event-Objekt von JS möglich, dass der Methode über den proxy()-Mechanismus automatisch übergeben wird:

Constr_CtrlO_Form.prototype.radio_click = function(e) {...}

e.target liefert dann den gewünschten Zeiger auf das HTML-Objekt. Dieser Zeiger lässt sich dann wiederum für jQuery-Selektionen und zugehörige Funktionen einsetzen.

Der $.proxy()-Mechanismus erlaubt so die vollständige Übergabe der Event-Behandlung an Methoden abstrakter Objekte. Das Verfahren lässt sich im Gegensatz zum Beispiel natürlich auch auf den Aufruf der Methoden anderer Objekte als des aktuell aktiven Objekts verallgemeinern.

jQuery’s .each()-Funktion und der this-Operator

Das obige Beispiel hat verdeutlicht, dass die Kontrolle über den this-Operator für die Delegation der Eventbehandlung an abstrakte Objekt-Methoden wichtig ist.

Nun delegiert auch die Funktion .each() eines jQuery-Objekts (sprich einer Selektion), die Durchführung von Aufgaben im Zusammenhang mit jedem der identifizierten HTML-Objekten an eine Funktion, die als Callback mit vordefinierten Parametern – nämlich (index, element) – festgelegt werden muss (s. https://api.jquery.com/each/). Wie lenkt man die Aufgabendurchführung aber statt dessen auf eine passende Methode eines CtrlOs um? Und wohin weist der this-Operator innerhalb der zu definierenden Callback-Funktion?

Betrachten wir zunächst, wie die .each()-Funktion im Zusammenhang mit Selektionen praktisch zum Einsatz kommt. Wir nehmen im nachfolgenden Beispiel an, dass bestimmte IMG-Tags einer Bilder-Galerie durch die CSS-Klasse “enlarge” gekennzeichnet sein sollen. Die Verwendung von .each() sieht dann im einfachsten Fall etwa so
aus:


// iterate over all (IMG-) tags with css class="enlarge"
// -----------------------------------------------------
$(".enlarge").each(
	function () {
		// Note: this in this function points to the HTML object, here an identified IMG tag 
		.....
		// Code to perform actions, e.g. on the HTML object
		// console.log("id des HTML-Elements : " + $(this).attr("id"); 
		..... 	
	}	
);

 
Wir führen eine Selektion durch und definieren innerhalb von each() eine Callback-Funktion, die dann bestimmte Dinge im Zusammenhang mit jedem der ermittelten HTML-Objekte des DOM-Baums der Webseite durchführt. Z.B. könnten wir dessen Attribute oder CSS-Eigenschaften verändern oder aber Event-Listener implementieren, etc..

Wichtig ist, sich zu vergegenwärtigen, dass der this-Operator innerhalb der Funktion “function() {…}”, die pro Element der Selektion ausgeführt werden soll, auf das aktuell betroffene HTML-Element verweist! Gemeint ist hier tatsächlich die JS-Referenz auf den DOM-Knoten – und kein JQuery-Objekt einer Selektion. Dieser Unterschied ist wichtig : Will man nämlich jQuery-Funktionen, die für Selektionen (also ein jQuery-Objekt) definiert sind, anwenden, so ist zuvor $(this) zu bilden !

“function() {…}” muss bestimmte formale Voraussetzungen bzgl. der Parameter erfüllen. Deshalb kann man “function() {…}” nicht so ohne weiteres durch Callback-Verweise auf beliebige Funktionsobjekte des JS-Codes ersetzen. Es ergibt sich daher die Frage:

Wie kann man über die innerhalb von each() definierten Callback-Funktion “function() {…}” Methoden eines CtrlOs aufrufen und die Referenz auf den DOM-Knoten dabei weiterverwenden?

Nehmen wir mal an, unser Code-Schnipsel von oben sei Teil einer Methode eines CtrlOs, welches wiederum als Element eines globalen Objects GOC definiert sei. Innerhalb des CtrlO-Konstruktors werde im Beispiel eine Initialisierungs-Methode “init_img_control()” aufgerufen; sie möge die Selektion von (IMG-) Tags anhand der CSS-Klase “enlarge” durchführen und pro (IMG-) Tag Aktionen zur späteren Bildkontrolle ausführen. Diese Aktionen seien in der Methode “set_img_nr()” des CtrlO definiert:


GOC = new Constr_GOC(); 

function Constr_GOC() {

    ....
    this.CtrlO_Manipulate_Pics = new this['Constr_CtrlO_Manipulate_Pics']( ...parameter, ...);
    ....
    ....
    // Konstruktor eines CtrlO - this refers to the GOC 
    // -----------------------
    this.Constr_CtrlO_Manipulate_Pics = function(.. parameter, ...) {
        ....
        var numOfImgs = 0; 
        ....
        // "this" refers here to the CtrlO which is created via the present constructor 		
        ...
        this.init_img_control();
        .... 
    };

    // CtrlO-Methode init_img_control()
    // -----------------------------------	
    this['Constr_CtrlO_Manipulate_Pics'].prototype.init_img_control = function() {
	
        // this refers to the CtrlO
        ....
        $(".enlarge").each(
            function () {
                // Note: this points here to an HTML object, 
                // an identified img tag with the CSS class "enlarge" 
                ....
                // Code to perform actions, e.g. on the HTML object

                // console.log("id des HTML-Elements : " + $(this).attr("id"); 

                // ... We WANT TO CALL set_img_nr() - BUT HOW TO DO IT PROPERLY ??? ....
                .....
            }	
        );
        .....
        .....
    };

    // CtrlO-Methode set_img_nr() - to be used for each IMG-tag
    // -----------------------------------------------------------	
    this['Constr_CtrlO_Manipulate_Pics'].prototype.set_img_nr = function(ref_to_img_tag) {
        ....
        var img_nr = 0; 
        // Count the number of identified IMG tags
        this.numOfImgs++; 
        img_nr = this.numOfImgs; 
        ... 
        $(ref_to_img_tag).attr("imgNum", img_nr.toString() );  
        ....
    };

}

 
Wir haben hier nebenbei für Interessierte noch eine weitere zusätzliche Kapselung im GOC vorgeführt:

Die Konstruktor-Funktion für das CtrlO kann selbst als Element des globalen GOC definiert werden. Das GOC-Objekt erzeugt dann das CtrlO als weiteres Unterobjekt durch expliziten Verweis auf das als Konstruktor zu verwendende Funktionsobjekt (this[“Name_des_Funktionsobjekts“]) nach dem new-Operator. Dass sowas tatsächlich geht, ist hier aber nur eine Randnotiz (siehe hierzu den Blog-Artikel Javascript: Einsatz des new-Operators mit Variablen und dynamischer Vorgabe der Konstruktorfunktion).

Im Beispiel wird per “$(..).each()”-Funktion über selektierten Objekte iteriert; wir möchten dabei z.B. gerne jedes der per $(“.enlarge”) ermittelten <IMG>-Tags um eine neues künstliches Attribut ergänzen; so könnten wir in diesem Attribut etwa eine Nummer hinterlegen, die wir später zur Identifikation des Bildes nutzen. Die Attribut-Ergänzung soll im Beispiel über die Methode “set_img_nr()” des CtrlOs GOC[“CtrlO_Manipulate_Pics”] geschehen.

Das Dumme ist nun, dass this innerhalb von “function() {…}” auf das aktuell identifizierte HTML-Element – also ein <IMG class=”enlarge” … >-Tag – verweist. Wir müssen das CtrlO daher anders referenzieren. Aus Gründen der besseren Wiederverwendbarkeit wollen wir zur Identifikation des CtrlOs aber keinen Bezug auf eine explizite Bezeichnung von Unterobjekten des GOC heranziehen; wir woll vielmehr auf ein geeignetes “this” zurückgreifen, das unmittelbar auf das CtrlO verweist. Andererseits soll aber die CtrlO-Methode “set_img_nr()” auch einen Verweis auf den aktuellen HTML-Knoten (also das IMG-Tag) als Parameter erhalten.

Ein wenig Nachdenken führt zu folgender Lösung für die Methode init_img_control() :


    this['Constr_CtrlO_Manipulate_Pics'].prototype.init_img_control = function() {
	
        // this still refers to the CtrlO
        ....
        ....
        // Use a helper variable to store the reference to the CtrlO

       var this_CtrlO = this;  // "this_CtrlO" points to the CtrlO (=GOC["CtrlO_Manipulate_Pics"])
                               // we could have called the helper variable also "that"
        ....
        $(".enlarge").each(
            function () {
                // Note: "this" now points to the HTML object, here an identified img tag 
                // Note: the variable "this_CtrlO" is found by implicit search in nested JS-functions 
                ....				
                .....
                // Code to perform actions, e.g. on the HTML object
                // console.log("id des HTML-Elements : " + $(this).attr("id");
                .....
                // we refer to the appropriate method of the CtrlO via the helper variable  
                // and provide the reference to the <IMG> tag (=this) as a parameter 

                this_CtrlO.set_img_nr(this); 
                ....
            }	
        );
        .....	
    };

 
Alles gut!
Der Profi erkennt sofort den klassischen Trick: Wir merken uns vor der Durchführung der jQuery-Selektion die Referenz auf das CtrlO in einer lokalen Hilfs-Variablen “this_CtrlO”. Da wir uns vor der Selektion ja noch im Kontext
einer gewöhnlichen Objekt-Methode befinden, verweist “this” dort ja noch auf das übergeordnete Objekt.

In der Callback-Funktion “function() {…}”, die innerhalb von .each() definiert wird, rufen wir dann die gewünschte Methode des CtrlO explizit unter Nutzung der Objekt-Referenz “this_CtrlO.Methodenname” auf. Die Variable wird im Lösungsansatz durch implizite Suche im Kontext der umgebenden, kapselnden Funktion init_img_control() gefunden.

Innerhalb der Callback-Funktion “function() {…}” verweist this nun jedoch auf das aktuell zu behandelnde HTML-Objekt der Selektion. Diese Referenz auf das HTML-Objekt können wir deshalb als Parameter (this) an die Objektmethode übergeben. Das zu bearbeitende HTML-Objekt kann danach auch in der CtrlO-Methode eindeutig identifiziert und bearbeitet werden.

Hinweis: Das zwischenzeitliche Speichern der this-Referenz in einer anderen Variablen entspricht in anderen Lehrbuchbeispielen oft dem Einsatz einer Hilfsvariablen “that”.

Unschöne impliziter Variablen-Suche

Wir haben uns mit dem obigen Lösungsansatz allerdings ein unschönes Thema für die Code-Pflege eingehandelt, das mit dem Hoisting von Variablen in Funktionen zu tun hat und in komplexeren Codes bei Unachtsamkeit zu Problemen führen kann: Die Variable “this_CtrlO” darf innerhalb von “function() {…}” an keiner Stelle über var-Statements redefiniert werden – auch nicht nach dem Statement “this_CtrlO.set_img_nr(this);”. Man erkennt leider nicht zwingend, dass es sich eigentlich um einen Parameter handelt, der nach unten durchgereicht wird. Das würde man gerne etwas expliziter sehen.

Man könnte diesem Thema einerseits dadurch ausweichen, dass man die Werte in Variablen speichert, die über das GOC explizit adressiert werden. Das würde unsere Kapselung aber auch wieder durchbrechen. Besser erscheint eine Übergabe der Referenz als Parameter in den each()-Bereich. Ein anderer Ansatz besteht deshalb in der expliziten Übergabe an eine sog. “immediate function” – das ist zwar auch nicht optimal, aber schon ein wenig besser. Man erkennt die Variable wenigstens als Parameter. Ganz nach unten durchreichen kann man die Referenz auf das CtrlO in diesem Falle halt leider nicht.


    this['Constr_CtrlO_Manipulate_Pics'].prototype.init_img_control = function() {

        // this still refers to the CtrlO
        ....
        ....
        // Use a helper variable to store the reference to the CtrlO

        var this_CtrlO = this;  // "this_CtrlO" points to the CtrlO (=GOC["CtrlO_Manipulate_Pics"])
                                // we could have called the helper variable also "that"
        ....
        ( function (pointer_CtrlO) {	
              $(".enlarge").each(
                  function () {
                      // Note: "this" now points to the HTML object, here an identified img tag 
	
                      // get external reference to the CtrlO
                      var CtrlO = pointer_CtrlO; // best at the top of the function code 
                      ....				
                      .....
                      CtrlO.set_img_nr(this); 
                      ....
                  }	
              );
          }
        )(this_CtrlO);
        .....	
    };

 
Man beachte: Die “immediate function” wird im Kontext des vorliegenden Beispiels in der Initialisierungssfunktion “init_img_control” nur genau einmal ausgeführt.

Fazit

Über die Callback-Funktion, die innerhalb der “.each()”-Funktion für Selektionen zu definieren ist, lassen sich auch Methoden eines abstrakten Control Objects [CtrlO] zur Behandlung der selektierten HTML-Objekte aufrufen. Das gilt selbst dann, wenn die Selektion $(..).each( ..) innerhalb einer anderen
Methode desselben CtrlOs vorgenommen wird. Dem Kontextwechsel des this-Operators in den verschiedenen Code-Bereichen der Funktionen beugt man durch rechtzeitige Zwischenspeicherung in einer geeigneten lokalen Hilfsvariable im Scope der kapselnden Methode vor. Die this-Referenz auf das selektierte, aktuell zu behandelnde HTML-Objekt kann man den CtrlO-Methoden als Parameter übergeben. Damit können Aufgaben, die im Rahmen von .each() durchzuführen sind, vollständig an geeignete Methoden von Control Objects delegiert werden.

Viel Spaß weiterhin mit jQuery, Javascript und der Kapselung von Funktionalität in Objekt-Methoden.

Javascript: Einsatz des new-Operators mit Variablen und dynamischer Vorgabe der Konstruktorfunktion

In PHP gibt es die Möglichkeit, den “new” Operator mit einer Variablen zu kombinieren. Dies entspricht einer indirekten Adressierung des Konstruktors. Beispiel :

$ClassName = "Class_Test"; 
$Obj = new $ClassName( param1, param2, ...); 

 
Probiert man etwas Ähnliches unter Javascript, so erleidet man Schiffbruch. Der String-Wert einer Variablen wird vom “new” Operator nicht als Bezeichnung einer Konstruktorfunktion interpretiert.

Sieht man typische Webseiten oder auch Bücher nach der Verwendung des “new”-Operators durch, so wird nach dem “new”-Operator fast durchgehend die Benutzung eines Literals beschrieben, das dem Namen der definierten Funktion entspricht:

function meterpreter() {
	this.alpha = 5; 
}      
var Obj = new meterpreter(); 
echo "value of property alpha = " +  Obj.alpha;    

 
Die Verwendung eines Literals scheint eine indirekte, dynamische Adressierung auszuschließen.

Nun passiert es einem aber auch unter Javascript, dass man ein Objekt gerne aus einem dynamischen Kontext heraus erzeugen möchte. Dann will man den “new”-Operator mit einer Variablen kombinieren, die dynamisch ermittelt wurde, und deren Wert irgendwie die Konstruktorfunktion referenzieren soll. Ein Beispiel:

Man möchte beim Startup einer Webseite eine Reihe von (Singleton-) Objekten erzeugen. Die Namen der zugehörigen
Konstruktorfunktionen seien in einem Array gespeichert. Ein Loop über das Array könnte die Objekterzeugung durchführen, wenn der “new”-Operator mit dem jeweiligen Array-Eintrags verbunden werden könnte und dadurch dann indirekt auch der jeweils benötigte der Konstruktor aufgerufen werden würde. Wie also nutzt man den “new”-Operator zusammen mit Variablen unter JS?

Hier hilft es, sich daran zu erinnern, dass definierte JS-Funktionen Objekten entsprechen, die sich Variablen zuordnen lassen. Nehmen wir in Anlehnung an das obere Beispiel an, wir hätten ein globales Objekt definiert, dass wir GOC (Global Object Controller) nennen wollen und das ein Array mit Namen für potentielle (Singleton-) Objekte beinhaltet. Nehmen wir ferner an, dass wir zugehörige Konstruktorfunktionen bestimmten Variablen des GOC mit normierten Namen zugeordnet hätten:

this.GOC = new Global_Object_Controller();  
this.GOC.createObjects(); // hier konstruieren wie Objekte als Elemente des GOC

function Global_Object_Controller() {
	this.ay_ctrl_obj_names  = new Array('Gallery', 'Ajax', ....);
	this.num_ctrl_objs = this.ay_obj_names.length;

	// Konstruktor Definition
	// ----------------------- 
	this.Constr_Gallery = function( param ) {
	 	.....	
		this.alpha = param + 1; 
		.....
		.....
 	};

	// Method definition of Constr_Gallery 
	// Wir verwenden zur Abwechslung mal die an Arrays angelehnte Notation ...
	this['Constr_Gallery'].prototype.do_something = function() {
		...
		this.obj_num += 10; 
		...
	};  
	.....
	..... 	

	// Konstruktor Definition
	// ----------------------- 
	this.Constr_Ajax = function( param ) {
	 	.....	
		this.obj_num = param + 1; 
		.....
		.....
 	};
	....
	....
}

 
Dann können wir z.B. über eine Methode tatsächlich Objekte dynamisch erzeugen lassen – und zwar z.B. über folgenden simplen Trick:

Global_Object_Controller.prototype.createObjects = function() {
	
	var ctrl_obj_name = ''; 
	var constr_name = ''; 
	....
	for (i=0; i<this.num_ctrl_objs; 
i++) {
		...
		ctrl_obj_name = "Obj_" + this.ay_ctrl_obj_names[i]; 
 		constr_name   = "Constr_" + this.ay_ctrl_obj_names[i];

		// Indirekter Aufruf des Konstruktors über eine Variable (hier des GOC)  
		// *******************************************************************
		this[ctrl_obj_name]  = new this[constr_name](i); 
		// ******************************************************************** 		
		// ist identisch mit 
		// window.GOC[ctrl_obj_name] = new window.GOC[constr_name](i); 		
	
		// console.log("Objekt " + ctrl_obj_name + " im GOC kreiert");  
  		....
	}	
	.....
	// console.log("Obj_Gallery.obj_num = " + this["Obj_Gallery"].obj_num ); // value=1 
	this["Obj_Gallery"].do_something(); 
	// console.log("Obj_Gallery.obj_num = " + this["Obj_Gallery"].obj_num ); // value=11  
	// console.log("Obj_Ajax.obj_num = "    + this["Obj_Ajax"].obj_num );    // value=2  
	
	.....
};   

 
Das funktioniert! Man erkennt, dass in unserem sehr simplen Beispiel die gewünschten Objekte über Variablenaufrufe als Elemente des GOC-Objekts erzeugt werden.

Man kann den “new”-Operator also tatsächlich mit Variablen (irgendwelcher Objekte oder von “window”) kombinieren, wenn diesen Variablen bereits sinnvolle Konstruktorfunktionen zugeordnet wurden. Das erinnert an den Callback-Mechanismus – hier allerdings für den “new”-Operator.

Die indirekte Adressierung erfolgt im Gegensatz zu PHP dadurch, dass man den “Namen” der Variablen im Zuge des Algorithmus dynamisch festlegt und darüber dann auf den Konstruktor als das Funktions-Objekt referenziert. Das erfordert zwar ein etwas anderes Vorgehen, schränkt einen aber im Vergleich zu PHP in der Zielerreichung einer dynamischen und indirekten Konstruktor-Referenzierung nicht ein.

Dadurch wird man bzgl. der Objektgenerierung sehr viel flexibler, als wenn man sich immer mit Literalen herumschlagen müsste.

Off Topic:

Das Beispiel zeigt übrigens, dass Konstruktorfunktionen nicht immer zwingend im globalen Kontext (window) platziert werden müssen. Sie können auch jederzeit Variablen eines bereits definierten übergeordneten Objekts (oder seines Konstruktors) zugeordnet werden. Dies eröffnet in bestimmten Fällen weitere Möglichkeiten der Kapselung von Code.
In der Praxis muss man sich eine Zuordnung von Konstruktor-Funktionen zu Variablen aber gut überlegen. Schon aus Gründen der Codeverwaltung wird man Konstruktorfunktionen für wichtige Objekt in separaten, eigenen Dateien aufbewahren. Beim Laden der Dateien werden die Funktionen dann typischerweise in den globalen Kontext platziert.
Zudem gilt: In komplexen Codes, die z.B. mit Eclipse oder anderen Tools gewartet werden, ist die Zuordnung von Konstruktorfunktionen zu Variablen eines anderen Konstruktors möglicherweise mit dem Nachteil verbunden, dass Code-Outliner diese Sub-Konstruktoren, zugehörige Variable und Funktionen ggf. nicht mehr als eigene Objekte ausweisen – sie sind dann einer einfachen Navigation im Code über den Outliner nicht mehr zugänglich.

Will man die Konstruktoren deshalb aus guten Gründen unabhängig von anderen Objektbeschreibungen definieren, so ist das Codebeispiel leicht zu modifizieren: Man definiert die Konstruktorfunktionen global und nicht im GOC. Und ruft sie dann im GOC und dessen Loop wie folgt auf:

this[ctrl_obj_name] = new window[constr_name](i);

Viel Spaß weiterhin mit Javascript!

nPA, eID und Open eCard unter Linux/Opensuse

Vor kurzem musste ich mich mit der Frage auseinandersetzen, wie ich die eID des neuen Personalausweises [nPA] unter Linux nutzen kann. Da ich in Bayern wohne, war ich u.a. daran interessiert, Zugang zur sog. BayernID und einem damit verbundenen “Bürgerkonto” zu bekommen, das von der Landesregierung über ein Infrastruktur der AKDB zentral bereitgestellt wird. Dieses Konto kann in allen sog. “Bürgerservice”-Portalen der in Bayern an die AKDB angeschlossenen Kommunen verwendet werden kann. Der im Alltag spürbare Nutzen ist aufgrund des noch sehr begrenzten Angebots an transaktionalen Online-Diensten, in denen der eID-Einsatz die Schriftformerfordernis abdeckt, allerdings noch relativ bescheiden. Aber das ist eine andere Diskussion …

Welche Erfahrung macht man nun, wenn man sich als Linux-Nutzer registrieren will? Leider wird man umgehend frustriert und enttäuscht:

Linux-User werden von Hauptseiten der Portal- und Dienstebetreiber schlichtweg ignoriert; sie tauchen in den Anleitungen zum Einsatz der eID flächendeckend nicht auf. Grundsätzlich wird die AusweisApp2 als Voraussetzung der eID-Nutzung genannt. Diese Anwendung steht jedoch nur für MS Windows und Apple OS X zur Verfügung. Der übliche Verweis auf die Website “https://www.ausweisapp.bund.de/startseite/” für weitere Informationen lässt den Linux-User dann jedoch im Regen stehen. Nach mühsamer Suche erfährt man unter FAQs bzw. in einem Forum lapidar, dass Governikus angeblich auf die am häufigsten eingesetzten Betriebssysteme gezielt habe.

Aufregen nutzt hier nichts – die eigentlich relevante Frage, wie hoch der Prozentsatz der E-Government-Willigen pro Betriebssystem ist und was das dann in absoluten Zahlen bedeutet, wurde wohl nicht als relevant angesehen. Im Ergebnis ist festzuhalten, dass die Möglichkeit zur Plattformneutralität trotz Opensource-Politik von Governikus nicht genutzt hat. Zudem wurde leider die Chance vertan, gerade bei denjenigen Staatsbürgern Pluspunkte und Vertrauen zu gewinnen, die E-Government befürworten und dabei den deutschen Datenschutz womöglich ernster nehmen als ein bestimmter Betriebssystemhersteller, der für seine Nutzungsbedingungen und den umfassenden Zugriff auf personenbezogene Daten im Rahmen von Standardinstallation kürzlich von einer deutschen Verbraucherzentrale heftig kritisiert wurde.
http://www.sueddeutsche.de/digital/klage-windows-verbraucherzentrale-geht-gegen-microsoft-vor-1.2886619

Open eCard

Welche Alternative hat man nun als Linux-User, der E-Government-Anwendungen in Kombination mit der eID nutzen will? Governikus verweist auf das “persoapp”-Projekt. Das ist jedoch nicht fertig – unter Opensuse Leap mit Java OpenJDK 1.8 und KDE 5 lief die Test-Anwendung jedenfalls (noch) nicht. Auch ein Java-Webstart von des Testseite führte nicht zum Erfolg.

Nach ein wenig Recherche wird man aber dank anderer engagierter Zeitgenossen fündig: Es gibt auch das Open eCard-Projekt – siehe:
https://www.openecard.org/startseite/
Dort kann man sich eine Java Web Start Applikation und bei Interesse den zugehörigen Code herunterladen. Angemerkt sei, dass die Open eCard-Anwendung Anfang 2016 vom BSI in puncto Sicherheit zertifiziert wurde. Siehe hierzu:
http://www.pro-linux.de/news/1/23138/bsi-zertifiziert-offenen-eid-client.html

Voraussetzung der Anwendung ist eine JAVA Run Time Umgebung JRE >= Version 1.7. Hat man ferner einen NFC-fähigen Kartenleser, für den der Hersteller Linux-Treiber bereitstellt (etwa von ReinerSCT), so nimmt die Open eCard-Anwendung den Kartenleser anstandslos wahr und zeigt ggf. an, dass (k)eine RFID-Karte oder eben der
neue Personalausweis eingelegt ist.

eID_opeecard_0
eID_opeecard_01

Unter KDE platziert sich die Anwendung in der Systemkontrollleiste – und wartet im Hintergrund. Ein Klick öffnet unter KDE 4 ein Anwendungsfenster. Das funktioniert unter KDE5 (noch) nicht – das tut aber der späteren Funktionalität in Kombination mit E-Government Web-Anwendungen im Browser keinen Abbruch.

Die Anwendung kommt extrem schlicht daher; es gibt kaum Infos und Einstellmöglichkeiten; das Layout ist maximal schmucklos.

eID_opeecard_02

Wirklich zu werkeln beginnt die Anwendung dann, wenn eine E-Government-Web-Anwendung im Browser – z.B. das AKDB-Konto beim Login – die eID auslesen will. Man wird dann vom Kartenleser wie der Open eCard-Anwendung vorab über die Berechtigung der zugreifenden Instanz informiert und – soweit noch nicht getan – zum Ein-/Auflegen des nPA in das Lesegerät aufgefordert.

eID_opeecard_1

Zudem wird rudimentär und für den Unkundigen etwas kryptisch der Typus der Daten angezeigt, die ausgelesen werden.

eID_opeecard_2

Unter “pseudonym” kann sich nicht jeder was vorstellen. Weiter helfen dem Interessierten Bürger hier Informationen dieser Links:
http://www.die-pseudonym-funktion.de/?navigation=login-per-pseudonym-funktion-des-personalausweises
http://www.personalausweisportal.de/DE/Wirtschaft/Diensteanbieter-werden/Einsatzmoeglichkeiten/Pseudonymer-Zugang/pseudonym_node.html
http://www.die-eid-funktion.de/

Im Falle komplexerer Transaktionen als einem Login werden hier deutlich mehr personenbezogene Daten angezeigt. Z.B. bei der Abfrage der gespeicherten nPA-Daten über eine Website des BMI https://www.buergerserviceportal.de/bund/ausweisapp/bspx_selbstauskunft/index.jsp

eID_opeecard_4

Interessanterweise findet Firefox die genannte Seite des BMI nicht vollständig sicher; das letztlich referenzierte Zertifikat der AKDB) ist aber OK.

eID_opeecard_5

eID_opeecard_6

Ja, ja, … Querverweis zur Anwendung nicht ganz glücklich implementiert. Unter dem Bayernportal läuft die gleiche Auskunftsanwendung dagegen ohne Sicherheitswarnung. Man versuche es selbst unter https://www.buergerserviceportal.de/bayern/freistaat/bspx_selbstauskunft

Nach PIN-Eingabe und dem Auslesevorgang wird die Kontrolle dann wieder an die Web-Anwendung abgegeben. Dankenswerterweise fordert einen “Open eCard” dann auf, den Personalausweis wieder aus dem Kartenleser zu entfernen.

eID_opeecard_3

Ich habe inzwischen mehrere kommunale Verwaltungsportale besucht und immer dann, wenn die Bedienungsanleitungen die AusweisApp2 verlangten, unter Linux auf die Open eCard zurückgegriffen. Konnte bislang kein Problem erkennen.

Fazit

Also – wenn auch nicht mit der AusweisApp2 und ohne Unterstützung von Governikus:

Dank der Leute, die zu Open eCard beigetragen haben, kann auch der Linuxer E-Government Dienste in Deutschland nutzen, die die eID erfordern. Mit BSI Sicherheitszertifizierung. Ich jedenfalls danke dem Open eCard Team für seine Anstrengungen und Verdienste um die Zertifizierung recht herzlich.