JavaScript und HTML

Einbinden von JavaScript: Externe Datei

Eigene JavaScript-Datei

  • JavaScript kann von mehreren Seiten genutzt werden
  • Browser kann Skript cachen
  • Normalfall für größere Skripte
<script src="helloworld.js"></script>

Einbinden von JavaScript: Eingebettet

JavaScript direkt in HTML-Datei eingebettet

  • Skript gilt nur für diese Datei
  • keine Wiederverwendung
  • <noscript>-Tag für Browser ohne JavaScript-Support
<script>
// <![CDATA[
   alert("Hello World!");
// ]]></script>
<noscript><p>Bitte aktivieren Sie JavaScript !</p></noscript>

Einbinden von JavaScript: Inline

JavaScript direkt in HTML-Tags

  • Einige HTML-Tags erlauben die Deklaration von Event-Handlern (siehe unten)
  • Anstatt eines Funktionsaufrufs kann man hier auch direkt JavaScript einsetzen
<div style="background-color: lightgrey; width: 300px; height: 50px;"
 onmouseover="alert('Juhu, getroffen');">Berühr mich</div>

JavaScript als Link-Ziel

  • JavaScript kann auch als Ziel eines Links definiert werden
  • Anwendungen
    • Sprungziele aus Parametern berechnen
    • Absende-Button eines Formulars als Link
    • Überprüfung der Benutzereingaben vor dem Absenden
<a href="javascript: alert('Ich wurde geklickt!');">
  Klick mich
</a>

Verzögertes Laden

JavaScript kann erst auf DOM zugreifen, wenn Seite vollständig geladen ist

  • kein-Attribut: Skript wird ausgeführt, wenn der Browser das <script>-Tag sieht. Weitere Ladevorgänge werden verzögert bis Skript fertig ist
  • defer-Attribut: Skript wird erst ausgeführt, wenn DOM fertig
  • async-Attribut: Skript wird sofort ausgeführt und Seite wird weiter geladen
<script src="normal.js"></script>
<script defer src="defer.js"></script>
<script async src="async.js"></script>

Ereignisse in HTML - Maus

Ereignis Beschreibung
onclick Maus wurde geklickt
ondblclick Maus wurde doppelt geklickt
onmousedown Maus-Knopf ist gedrückt
onmouseup Maus-Knopf wurde losgelassen
onmouseover Maus betritt ein Element
onmousemove Maus bewegt sich im Element
onmouseout Maus hat Element verlassen

Ereignisse in HTML - Tastatur

Ereignis Beschreibung
onkeydown Taste ist gedrückt
onkeyup Taste wurde losgelassen
onkeypress Taste würde gedrückt und losgelassen

Ereignisse in HTML - Formulare

Ereignis Beschreibung
onchange Daten wurden geändert
onfocus Feld hat Fokus
onblur Anwender verlässt Feld
onsubmit Formular soll abgeschickt werden (false als Rückgabewert verhindert das Absenden)
onreset Formular wird zurückgesetzt

Ereignisse in HTML - Datei

Ereignis Beschreibung
onload Datei wurde geladen
onunload HTML-Datei wurde verlassen
onabort Laden der Seite wurde abgebrochen

Zeitsteuerung von JavaScript

Verzögerte Ausführung

  • window.setTimeout(funktion, verzögerung);
  • Verzögerung in Millisekunden

Periodische Ausführung

  • Periodendauer in Millisekunden
  • Rückgabewert identifiziert Timer-Objekt (es können mehrere parallel laufen)
let p = window.setInterval(funktion, periodendauer);
window.clearInterval (p);

Beispiel: Zeitsteuerung

let counter = 0;
let id;

let handler = function() {
    document.getElementById("counter")
            .firstChild.nodeValue = counter;
    counter++;
}

function startTimerDemo() { id = window.setInterval(handler, 100); }

function stopTimerDemo() { window.clearInterval(id); }

 

0

Risiko JavaScript

JavaScript hat vollen Zugriff auf die Daten einer Seite

  • kann Formularfelder auslesen und verändern
  • kann Seite verändern
  • kann Daten nachladen

Hieraus würde ein großes Risiko resultieren, wenn beliebige Skripte auf beliebige Inhalte zugreifen können

Sicherheitsmaßnahme: Same Origin Policy

Same Origin Policy

Ein Skript darf nur auf Daten zugreifen, die dieselbe (same) Herkunft (origin) wie es selbst haben

Origin bestimmt sich aus

  • Protokoll (http, https, ftp, file, …)
  • Host (z. B. www.example.com)
  • Port (z. B. 80)

Ausnahme: ein Skript kann anfordern, dass statt des Hosts die Domain verwendet wird (über document.domain)

Beispiel: Same Origin Policy

Skript stammt von http://store.example.com/dir/page.html

URL Zugriff
http://store.example.com/dir/inner/another.html JA
http://store.example.com/dir2/other.html JA
https://store.example.com/secure.html Nein
http://store.example.com:81/dir/etc.html Nein
http://news.example.com/dir/other.html Nein
http://store.foo.com/dir/page.html Nein

CORS

Cross-Origin Resource Sharing (CORS): Erlaubt es, die Same Origin Policy kontrolliert zu umgehen. Es kommt zum Einsatz bei

  • XMLHttpRequest und Fetch APIs
  • Web Fonts
  • WebGL Texturen
  • Bilder und Videos, die auf einen Canvas gezeichnet werden
  • CSS-Shapes

Zwei unterschiedliche Arten von CORS- Requests

  • Simple Requests
    • erfolgen per GET, HEAD oder POST
    • haben einen Content-Type von: application/x-www-form-urlencoded, multipart/form-data oder text/plain
  • Preflighted Requests
    • alle anderen Requests
    • dürfen erst nach einem vorhergehenden OPTIONS-Request durchgeführt werden (dem Preflight Request)
    • Preflight-Request fragt den Server mit der Ressource, ob sie geladen werden darf. Wenn OK, dann kommt der richtige Request

CORS-Headers: Client

Der Client fragt die CORS-Regeln mit diesen Headern an

  • Origin: <origin>
    Die Quelle (Serverteil der URL) des Cross-Origin-Zugriffs. Dies ist der Server, von dem das JavaScript geladen wurde, das die Anfrage macht
  • Access-Control-Request-Method: <method>
    Teilt dem Server bei einem Preflight-Request per OPTIONS mit, welche die spätere HTTP-Methode sein wird
  • Access-Control-Request-Headers: <field-name> ...
    Teilt dem Server bei einem Preflight-Request mit, welche Header der tatsächliche Request tragen wird

CORS-Headers: Server

Der Server sendet einen CORS-Header zurück

  • Access-Control-Allow-Origin: <origin> | *
    Legt die URL (<origin>) fest, von der Ressourcen geladen werden dürfen
  • Access-Control-Expose-Headers: <header-name> ...
    Legt die Header fest, die von JavaScript aus gelesen werden dürfen
  • Access-Control-Allow-Headers: <header-name>...
    Steuert die erlaubten Header bei dem Request
  • Access-Control-Allow-Credentials: true
    Zeigt an, ob der Request mit Cookies durchgeführt werden kann (3rd-Party-Cookie)
  • Access-Control-Max-Age: <delta-seconds>
    Steuert die Zeit, für die das Ergebnis eines Preflight-Requests im Cache gehalten werden darf
  • Access-Control-Allow-Methods: <method>[, <method>]*
    Spezifiziert, welche Methoden erlaubt sind

Beispiel: GET-Request

Client: Anfrage an other.com
GET /resources/public-data/ HTTP/1.1
Host: other.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://this.com/simpleXSInvocation.html
Origin: http://this.com
Server: Antwort von other.com
HTTP/1.1 200 OK
Date: Mon, 03 Oct 2022 00:23:53 GMT
Access-Control-Allow-Origin: *
Content-Type: application/xml

...

Beispiel: Preflight-Request

Client: Preflight-Request an other.com
OPTIONS /resources/post-here/ HTTP/1.1
Host: other.com
Connection: keep-alive
Origin: http://this.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
Sever: Preflight-Antwort von other.com
HTTP/1.1 200 OK
Date: Mon, 03 Oct 2022 01:15:39 GMT
Access-Control-Allow-Origin: http://this.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Content-Type: text/plain

Beispiel: Endgültiger Request

Client: Endgültiger Request an other.com
POST /resources/post-here/ HTTP/1.1
Host: other.com
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://this.com/examples/preflightInvocation.html
Content-Length: 55
Origin: http://this.com
Pragma: no-cache
Cache-Control: no-cache

<?xml version="1.0"?><person><name>Arun</name></person>
Server: Antwort von other.com
HTTP/1.1 200 OK
Date: Mon, 03 Oct 2022 01:15:41 GMT
Access-Control-Allow-Origin: http://this.com
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

...

CORS - Ich bin verwirrt…

Fragen

  • Wieso erlaubt der Zielserver des Requests den Zugriff?
  • Wieso legt nicht der Quellserver (von dem das Skript kam) fest, wohin die Skripte zugreifen dürfen?
  • Wie soll mich das vor Cross-Site-Scripting (XSS) schützen?

Antwort: Szenario für das CORS gedacht ist

  • this.com liefert eine Seite aus
  • Seite lädt JavaScript von this.com → darf auf this.com zugreifen
  • Seite lädt JavaScript von anderer Quelle (z. B. google.com) → darf nicht auf this.com zugreifen
  • Auf keinen Fall sollte google.com festlegen dürfen, was das Skript darf
  • CORS-Header von this.com erlauben dann selektiv den Zugriff für google.com
CORS ist kein Schutz vor XSS. Dafür muss man CSP nutzen

Content Security Policy

Content Security Policy erlaubt einem Server zu kontrollieren

  • was ein Skript auf der eigenen Seite machen darf
  • woher Bilder und andere Ressourcen geladen werden dürfen
  • ob Ressourcen nur per HTTPS geladen werden dürfen
  • ob Skripte auch direkt in <script>-Tags oder Event-Handler vorkommen dürfen (→ typisch für XSS)
CSP dient als Schutz vor XSS und Sniffing. Es hat keinen Einfluss auf die Same-Origin-Policy ⇒ CORS

CSP-Header

CSP wird über Header-Felder kontrolliert

  • Content-Security-Policy: <policy>
    Schaltet CSP ein und legt die Regeln (<policy>) fest
  • Content-Security-Policy-Report-Only: <policy>
    Schaltet CSP ein und legt die Regeln fest, blockiert die Ressourcen aber nicht, sondern erstellt nur einen Report

CSP-Header: Beispiele

Content-Security-Policy:

  • default-src 'self'
    Alle Ressourcen (Skripte, Bilder, …) müssen von derselben URL kommen
  • default-src 'self' example.com *.example.com
    Ressourcen können zusätzlich noch von example.com und allen Subdomains davon kommen
  • default-src 'self'; img-src *; media-src example.org example.net; script-src userscripts.example.com
    Bilder dürfen von jeder Quelle kommen, Andere Medien nur von example.org und example.net. Skripte ausschließlich von userscripts.example.com

Content-Security-Policy:

  • default-src https://www.example.com
    Alle Inhalte müssen per HTTPS geladen werden
  • default-src 'self' *.example.com; img-src *
    Bilder können von überall geladen werden, alle anderen Inhalte nur von der aktuellen Seite
  • script-src https://example.com/
    Scripts müssen von der Seite example.com kommen. Inline-Scripts und Eventhandler sind blockiert

Copyright © 2025 Thomas Smits