Übergeben von Base64-codierten Zeichenfolgen in der URL

Antworten:

206

Nein, Sie müssten es url-codieren, da base64-Zeichenfolgen die Zeichen "+", "=" und "/" enthalten können, die die Bedeutung Ihrer Daten ändern können - sehen Sie aus wie ein Unterordner.

Gültige base64-Zeichen sind unten aufgeführt.

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
Thiyagaraj
quelle
4
URL-Codierung ist Platzverschwendung, zumal base64 selbst viele Zeichen unbenutzt lässt.
Michał Górny
21
Ich bin nicht sicher, ob ich verstehe, was Sie sagen - die URL-Codierung ändert keines der Zeichen außer den letzten drei Zeichen in der obigen Liste, und dies soll verhindern, dass sie falsch interpretiert werden, da sie in URLs andere Bedeutungen haben. Das gleiche gilt für base64, die Originaldaten können binär oder so sein, aber sie sind in einer Form codiert, die mit einfachen Protokollen einfach übertragen werden kann.
Thiyagaraj
3
Erstens sollten Sie auch '+' entkommen, da es in Raum umgewandelt werden kann. Zweitens gibt es mindestens wenige Zeichen, die für die Verwendung in URLs sicher sind und nicht im Standardzeichensatz verwendet werden. Ihre Methode kann in bestimmten Situationen sogar die Größe der übertragenen Daten dreimal erhöhen . Wenn Sie diese Zeichen durch andere ersetzen, wird der Trick ausgeführt, während die gleiche Länge beibehalten wird. Und es ist auch eine Standardlösung.
Michał Górny
8
en.wikipedia.org/wiki/Base64#URL_applications - es wird deutlich, dass das Escapezeichen "die Zeichenfolge unnötig länger macht" und die alternative Zeichensatzvariante erwähnt.
Michał Górny
1
Aufgrund dieser Antwort diagnostizierte ich mein Problem als genau das, was es erwähnte. Einige der 64 Basiszeichen (+, /, =) wurden aufgrund der URL-Verarbeitung geändert. Als ich die Basis-64-Zeichenfolge per URL codierte, wurde das Problem behoben.
Chuck Krutsinger
272

Es gibt zusätzliche base64-Spezifikationen. (Einzelheiten finden Sie in der Tabelle hier ). Im Wesentlichen benötigen Sie jedoch 65 Zeichen zum Codieren: 26 Kleinbuchstaben + 26 Großbuchstaben + 10 Ziffern = 62.

Sie benötigen zwei weitere ['+', '/'] und ein Füllzeichen '='. Aber keiner von ihnen ist url-freundlich, also benutze einfach verschiedene Zeichen für sie und du bist fertig. Die Standardzeichen aus der obigen Tabelle sind ['-', '_'], aber Sie können andere Zeichen verwenden, solange Sie sie gleich dekodiert haben und nicht mit anderen teilen müssen.

Ich würde empfehlen, nur Ihre eigenen Helfer zu schreiben. Wie diese aus den Kommentaren auf der PHP-Handbuchseite für base64_encode :

function base64_url_encode($input) {
 return strtr(base64_encode($input), '+/=', '._-');
}

function base64_url_decode($input) {
 return base64_decode(strtr($input, '._-', '+/='));
}
Joe Flynn
quelle
53
Tolle Lösung, außer dass Komma in URLs nicht uneingeschränkt bleibt. Ich empfehle '~' (Tilde) oder '.' (Punkt) stattdessen.
Kralyk
11
@kralyk: Ich empfehle nur, urlencodewie in Rodrigo-Silveiras Antwort vorgeschlagen. Wenn Sie zwei neue Funktionen erstellen, um wenige Zeichen in der URL-Länge zu sparen, betreten Sie Ihr Haus durch das Fenster, anstatt nur die Tür zu benutzen.
Marco Demaio
5
@MarcoDemaio, ohne zu wissen, wie es verwendet wird, ist es unmöglich zu sagen, dass es nur ein paar Zeichen sind. Jedes codierte Zeichen hat die dreifache Länge, und warum sollte "+++ ..." keine gültige base64-Zeichenfolge sein? URLs haben Browser-Limits. Wenn Sie eine URL verdreifachen, können Sie diese Limits erreichen.
Leewz
10
@RandalSchwartz Tilde ist URL-sicher. Von RFC3986:unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
Kralyk
3
Da ,sollte urlencodiert werden, schlage %2Cich vor, ._- anstelle -_,der einzigen Variante in en.wikipedia.org/wiki/Base64#Variants_summary_table zu verwenden , die das Trailing =
PaulH
75

@joeshmo Oder anstatt eine Hilfsfunktion zu schreiben, können Sie einfach die base64-codierte Zeichenfolge urlencodieren. Dies würde genau das Gleiche tun wie Ihre Hilfsfunktion, jedoch ohne die Notwendigkeit von zwei zusätzlichen Funktionen.

$str = 'Some String';

$encoded = urlencode( base64_encode( $str ) );
$decoded = base64_decode( urldecode( $encoded ) );
Rodrigo-Silveira
quelle
2
Das Ergebnis ist nicht genau das gleiche. urlencode verwendet 3 Zeichen, um ungültige Zeichen zu codieren, und joeshmos Lösung verwendet 1. Es ist kein großer Unterschied, aber es ist immer noch eine Verschwendung.
Josef Borkovec
1
@ JosefBorkovec Wirklich? Dann würde dies auch bedeuten, dass die gleiche Anzahl von Bytes, die base64-> url-> codiert ist, eine Vielzahl unterschiedlicher resultierender Längen sein könnte, während die andere Lösung eine vorhersagbare Länge ergibt, oder?
Menschlichkeit und
@humanityANDpeace Ja, Urlencode ist eine beschissene Lösung, weil es die Größe bestimmter base64-Strings verdreifacht. Sie können den Puffer auch nicht wiederverwenden, da die Ausgabe größer als die Eingabe ist.
Navin
4
Die Erweiterung von 1 auf 3 Zeichen erfolgt bei durchschnittlich 3 von 64 Zeichen, sodass ein Overhead von 9% (2 *
3/64
Seien Sie vorsichtig mit /Zeichen, wenn Sie es nicht als GET-Parameter, sondern als Pfad in der URL übergeben. Es wird Ihren Weg ändern, wenn Sie nicht /auf beiden Seiten durch etwas anderes ersetzen .
NeverEndingQueue
41

Einleitende Anmerkung Ich bin geneigt, einige Erläuterungen zu veröffentlichen, da einige der Antworten hier etwas irreführend waren (wenn nicht falsch).

Die Antwort lautet NEIN . Sie können nicht einfach einen Base64-codierten Parameter innerhalb einer URL-Abfragezeichenfolge übergeben, da Pluszeichen in ein Leerzeichen innerhalb des globalen Arrays $ _GET konvertiert werden. Mit anderen Worten, wenn Sie test.php gesendet haben? MyVar = stringwith + sign to

//test.php
print $_GET['myVar'];

das Ergebnis wäre:
stringwith sign

Die einfache Möglichkeit, dies zu lösen, besteht darin, einfach urlencode()Ihre base64-Zeichenfolge zu erstellen, bevor Sie sie zur Abfragezeichenfolge hinzufügen, um die Zeichen +, = und / in% ## -Codes zu maskieren. Gibt zum Beispiel urlencode("stringwith+sign")zurückstringwith%2Bsign

Wenn Sie die Aktion verarbeiten, übernimmt PHP die automatische Dekodierung der Abfragezeichenfolge, wenn das globale $ _GET gefüllt wird. Zum Beispiel, wenn ich test.php? MyVar = stringwith% 2Bsign an gesendet habe

//test.php
print $_GET['myVar'];

das Ergebnis wäre:
stringwith+sign

Sie nicht wollen, urldecode()die $ _GET String als + 's zurückgegeben werden in Leerzeichen umgewandelt werden.
Mit anderen Worten, wenn ich dieselbe test.php gesendet habe? MyVar = stringwith% 2Bsign to

//test.php
$string = urldecode($_GET['myVar']);
print $string;

Das Ergebnis ist unerwartet:
stringwith sign

Es wäre sicher für rawurldecode()die Eingabe, jedoch redundant und daher unnötig.

Jeffory J. Beckers
quelle
1
Gute Antwort. Sie können PHP-Code ohne die Start- und End-Tags auf dieser Site verwenden, wenn die Frage mit PHP markiert ist (auch meistens ist dies aus dem Kontext der Frage ersichtlich). Wenn Sie am Ende einer Zeile zwei Leerzeichen einfügen, wird das angezeigt <br>, sodass Sie nicht viel HTML eingeben müssen. Ich hoffe das hilft, ich habe deine Antwort ein wenig bearbeitet, um sie noch weiter zu verbessern.
hakre
Vielen Dank für die Erwähnung, dass PHP die URL für Sie dekodiert. Das erspart mir, in ein Kaninchenloch zu fallen.
Cocest
Gute Antwort -> Sie möchten den zurückgegebenen $ _GET-String nicht urldecode (), da + in Leerzeichen konvertiert wird. Es wäre jedoch sicher, die Eingabe mit rawurldecode () zu versehen
MarcoZen
14

Ja und nein.

Der Basiszeichensatz von base64 kann in einigen Fällen mit herkömmlichen Konventionen kollidieren, die in URLs verwendet werden. Bei vielen Base64-Implementierungen können Sie den Zeichensatz jedoch so ändern, dass er besser mit URLs übereinstimmt, oder sogar mit einer (wie Pythons urlsafe_b64encode()).

Ein weiteres Problem, mit dem Sie möglicherweise konfrontiert sind, ist die Begrenzung der URL-Länge bzw. das Fehlen einer solchen Begrenzung. Da Standards keine maximale Länge festlegen, können Browser, Server, Bibliotheken und andere Software, die mit dem HTTP-Protokoll arbeiten, ihre eigenen Grenzen definieren. Sie können sich diesen Artikel ansehen: WWW-FAQs: Was ist die maximale Länge einer URL?

Michał Górny
quelle
8

Es ist eine base64url-Codierung, die Sie ausprobieren können. Es ist nur eine Erweiterung des obigen Codes von joeshmo.

function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function base64url_decode($data) {
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
Andy
quelle
Dies funktioniert für Daten, die mit Java codiert sindBase64.getUrlEncoder().withoutPadding().encodeToString()
4

Ich denke nicht, dass dies sicher ist, da z. B. das Zeichen "=" in der Rohdatenbasis 64 verwendet wird und auch zur Unterscheidung der Parameter von den Werten in einem HTTP-GET verwendet wird.

Mischa
quelle
1

Theoretisch ja, solange Sie die maximale Länge der URL und / oder der Abfragezeichenfolge für den Client oder Server nicht überschreiten.

In der Praxis kann es etwas schwieriger werden. Beispielsweise kann es eine HttpRequestValidationException in ASP.NET auslösen, wenn der Wert zufällig ein "Ein" enthält und Sie das nachfolgende "==" belassen.

Nicole Calinoiu
quelle
Sie erwähnen keine +, / oder = Zeichen, die URLs in bestimmten Fällen ungültig machen.
Will Bickford
0

Für die URL-sichere Codierung, wie base64.urlsafe_b64encode(...)in Python, funktioniert der folgende Code für mich zu 100%

function base64UrlSafeEncode(string $input)
{
   return str_replace(['+', '/'], ['-', '_'], base64_encode($input));
}
Igor Sazonov
quelle
-10

Ja, es ist immer sicher. Natürlich enthält base64: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= aber eine base64-codierte Zeichenfolge hat normalerweise keine +. +wird in ein Leerzeichen umgewandelt, führt zu einer falsch dekodierten Zeichenfolge. /ist sicher in einem get-Parameter-Paar. =befindet sich immer am Ende der Base64-codierten Zeichenfolge und die Serverseite kann =direkt auflösen .

Gouchaoer
quelle
Ich vermute, dass dies richtig ist, da die Experimente, die ich mit der Base64-Codierung (ohne URL-Codierung) durchgeführt habe, erfolgreich waren, aber ich frage mich, ob Sie eine Dokumentation bereitstellen können, um dies zu sichern?
Sean the Bean
1
Sie sagen "immer sicher", aber dann sagen Sie "normalerweise kein +". Also widersprichst du dir. Das + -Zeichen kann Probleme verursachen, wenn Sie es in Ihrer base64-Zeichenfolge haben.
Nick Humrich