Die Einrichtung läuft auch ohne HTTPS
crypto.randomUUID gibt es nur im secure context — HTTPS oder localhost, sonst nichts. Wer Flaro auf einem NAS betreibt und ihn unter http://192.168.x.x:8097 aufruft, hat die Funktion nicht, und die Geräteerkennung warf mitten in die Einrichtung „crypto.randomUUID is not a function". Das Konto liess sich nicht anlegen. Das ist nicht der Sonderfall. Ein Heimserver im eigenen Netz hat kein Zertifikat, und genau dort wird die Einrichtung durchlaufen. crypto.getRandomValues ist nicht so beschränkt und liefert denselben Zufall; daraus wird die UUID von Hand zusammengesetzt. Fällt auch das aus, bleibt Math.random — kein Zufall für Geheimnisse, aber hier geht es nur darum, zwei Browser auseinanderzuhalten, und gar keine Kennung wäre schlechter als eine schwache. Geprüft mit 20000 Durchläufen: alle entsprechen der Form von Fassung 4, keine Dublette. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3df873c8cd
commit
8a191d0faf
+41
-2
@@ -268,14 +268,53 @@ function geraetename(): string {
|
||||
return `${was} · ${/Firefox/.test(u) ? 'Firefox' : /Chrome/.test(u) ? 'Chrome' : 'Safari'}`;
|
||||
}
|
||||
|
||||
/** Eine zufällige Kennung — auch ohne HTTPS.
|
||||
*
|
||||
* **`crypto.randomUUID` gibt es nur im secure context.** Das ist HTTPS oder
|
||||
* `localhost`, sonst nichts. Wer Flaro auf dem NAS betreibt und ihn unter
|
||||
* `http://192.168.x.x:8097` aufruft, hat die Funktion nicht — und bekam
|
||||
* mitten in der Einrichtung „crypto.randomUUID is not a function" zu sehen.
|
||||
* Das ist nicht der Sonderfall, das ist der Normalfall im eigenen Netz.
|
||||
*
|
||||
* `crypto.getRandomValues` ist nicht so beschränkt und liefert denselben
|
||||
* Zufall. Die letzte Stufe mit `Math.random` taugt für Geheimnisse nicht —
|
||||
* hier geht es aber nur darum, zwei Browser auseinanderzuhalten, und gar
|
||||
* keine Kennung wäre schlechter als eine schwache.
|
||||
*/
|
||||
function zufallskennung(): string {
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
const bytes = new Uint8Array(16);
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
|
||||
crypto.getRandomValues(bytes);
|
||||
} else {
|
||||
for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
||||
}
|
||||
|
||||
// Fassung 4 und Variante nach RFC 4122 — Byte 6 und 8 tragen die
|
||||
// Kennzeichen. Ohne sie sind es sechzehn Zufallsbytes, die nur aussehen
|
||||
// wie eine UUID. Gesetzt wird beim Umwandeln und nicht über den Index:
|
||||
// `bytes[6]` gilt dem Typprüfer als womöglich undefiniert, und das
|
||||
// Gegenteil zu behaupten wäre die unaufrichtigere Lösung.
|
||||
const hex = Array.from(bytes, (b, i) => {
|
||||
const wert = i === 6 ? (b & 0x0f) | 0x40
|
||||
: i === 8 ? (b & 0x3f) | 0x80
|
||||
: b;
|
||||
return wert.toString(16).padStart(2, '0');
|
||||
}).join('');
|
||||
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
||||
}
|
||||
|
||||
/** Bleibt gleich, damit derselbe Browser nicht als zehn Geräte dasteht. */
|
||||
function geraetekennung(): string {
|
||||
const name = 'flaro.device';
|
||||
try {
|
||||
let vorhanden = localStorage.getItem(name);
|
||||
if (!vorhanden) { vorhanden = crypto.randomUUID(); localStorage.setItem(name, vorhanden); }
|
||||
if (!vorhanden) { vorhanden = zufallskennung(); localStorage.setItem(name, vorhanden); }
|
||||
return vorhanden;
|
||||
} catch { return crypto.randomUUID(); }
|
||||
} catch { return zufallskennung(); }
|
||||
}
|
||||
|
||||
/* ---------- Mediathek ---------- */
|
||||
|
||||
Reference in New Issue
Block a user