Passaggio di stringhe codificate in base64 nell'URL


Risposte:


206

No, dovresti codificarlo con l'URL, poiché le stringhe base64 possono contenere i caratteri "+", "=" e "/" che potrebbero alterare il significato dei tuoi dati - sembrano una sottocartella.

I caratteri base64 validi sono riportati di seguito.

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

4
La codifica URL è uno spreco di spazio, soprattutto perché la base64 stessa lascia molti caratteri inutilizzati.
Michał Górny,

21
Non sono sicuro di capire quello che stai dicendo: la codifica URL non altererà nessuno dei caratteri tranne gli ultimi tre caratteri nell'elenco sopra, e questo per impedire che vengano interpretati in modo errato poiché hanno altri significati negli URL. Lo stesso vale per base64, i dati originali potrebbero essere binari o altro, ma sono codificati in una forma che può essere trasmessa facilmente usando semplici protocolli.
Thiyagaraj,

3
In primo luogo, dovresti sfuggire anche a "+" poiché potrebbe essere convertito in spazio. In secondo luogo, ci sono almeno alcuni caratteri che sono sicuri per l'uso negli URL e non sono usati nel set di caratteri "standard". Il tuo metodo può persino aumentare la dimensione dei dati trasferiti tre volte in determinate situazioni; mentre la sostituzione di quei personaggi con qualcun altro farà il trucco mantenendo la stessa lunghezza. Ed è anche una soluzione abbastanza standard.
Michał Górny,

8
en.wikipedia.org/wiki/Base64#URL_applications - dice chiaramente che l'escape "allunga inutilmente la stringa" e menziona la variante del set di caratteri alternativo.
Michał Górny,

1
A causa di questa risposta, ho diagnosticato il mio problema come esattamente quello di cui parlava. Alcuni dei 64 caratteri di base (+, /, =) sono stati modificati a causa dell'elaborazione dell'URL. Quando I URL ha codificato la stringa 64 di base, il problema è stato risolto.
Chuck Krutsinger,

272

Ci sono ulteriori specifiche base64. (Vedi la tabella qui per i dettagli). Ma essenzialmente hai bisogno di 65 caratteri per codificare: 26 minuscole + 26 maiuscole + 10 cifre = 62.

Hai bisogno di altri due ['+', '/'] e un carattere di riempimento '='. Ma nessuno di loro è url friendly, quindi usa solo caratteri diversi per loro e sei pronto. Quelli standard della tabella sopra sono ['-', '_'], ma potresti usare altri caratteri purché tu li abbia decodificati allo stesso modo e non sia necessario condividerli con altri.

Consiglierei solo di scrivere i tuoi aiutanti. Come questi dai commenti sulla pagina di manuale di php per base64_encode :

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

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

53
Ottima soluzione, tranne la virgola non è riservata agli URL. Consiglio di usare '~' (tilde) o '.' (punto) invece.
kralyk,

11
@kralyk: raccomando solo di usare urlencodecome suggerito dalla risposta di rodrigo-silveira. Creare due nuove funzioni per salvare pochi caratteri nella lunghezza dell'URL, è come entrare in casa passando attraverso la finestra invece di usare semplicemente la porta.
Marco Demaio,

5
@MarcoDemaio, senza sapere come verrà utilizzato, è impossibile dire che sono solo pochi personaggi. Ogni carattere codificato avrà una lunghezza tripla e perché "+++ ..." non dovrebbe essere una stringa base64 valida? Gli URL hanno limiti del browser e triplicare un URL potrebbe farti superare questi limiti.
leewz,

10
@RandalSchwartz tilde è sicuro per gli URL. Da RFC3986:unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
kralyk,

3
Dato che ,dovrebbe essere urlencoded to %2C, suggerisco di usare al ._- posto di -_,like l'unica variante in en.wikipedia.org/wiki/Base64#Variants_summary_table che mantiene il trailing =
PaulH

75

@joeshmo O invece di scrivere una funzione di supporto, potresti semplicemente urlencode la stringa codificata base64. Questo farebbe esattamente la stessa cosa della tua funzione di aiuto, ma senza la necessità di due funzioni extra.

$str = 'Some String';

$encoded = urlencode( base64_encode( $str ) );
$decoded = base64_decode( urldecode( $encoded ) );

2
Il risultato non è esattamente lo stesso. urlencode utilizza 3 caratteri per codificare caratteri non validi e la soluzione di joeshmo utilizza 1. Non è una grande differenza, ma è comunque uno spreco.
Josef Borkovec,

1
@JosefBorkovec Davvero? Quindi questo significherebbe anche che lo stesso numero di byte base64-> url-> codificato potrebbe essere una varietà di diversa lunghezza risultante, mentre l'altra soluzione fornisce una lunghezza prevedibile, giusto?
umanità e

@humanityANDpeace Sì, urlencode è una soluzione di merda perché triplica la dimensione di alcune stringhe base64. Inoltre, non è possibile riutilizzare il buffer poiché l'output è più grande dell'input.
Navin,

4
L'espansione da 1 a 3 caratteri avviene in media su 3 su 64 caratteri, quindi è un sovraccarico del 9% (2 *
3/64

Fai attenzione al /carattere se lo passi non come parametro GET, ma come percorso nell'URL. Cambierà il tuo percorso se non lo sostituisci /con qualcos'altro su entrambi i lati.
NeverEndingQueue

41

Nota introduttiva Sono propenso a pubblicare alcuni chiarimenti poiché alcune delle risposte qui erano un po 'fuorvianti (se non errate).

La risposta è NO , non puoi semplicemente passare un parametro codificato base64 all'interno di una stringa di query URL poiché i segni più vengono convertiti in uno SPAZIO all'interno dell'array globale $ _GET. In altre parole, se hai inviato test.php? MyVar = stringwith + sign a

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

il risultato sarebbe:
stringwith sign

Il modo più semplice per risolverlo è semplicemente la urlencode()tua stringa base64 prima di aggiungerla alla stringa di query per sfuggire ai caratteri +, = e / ai codici% ##. Ad esempio, urlencode("stringwith+sign")restituiscestringwith%2Bsign

Quando elabori l'azione, PHP si occupa di decodificare automaticamente la stringa di query quando popola il globale $ _GET. Ad esempio, se ho inviato test.php? MyVar = stringwith% 2Bsign a

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

il risultato sarebbe:
stringwith+sign

Non si desidera urldecode()la stringa $ _GET restituita poiché i + saranno convertiti in spazi.
In altre parole, se ho inviato lo stesso test.php? MyVar = stringwith% 2Bsign to

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

il risultato è un imprevisto:
stringwith sign

Sarebbe sicuro per rawurldecode()l'input, tuttavia, sarebbe ridondante e quindi non necessario.


1
Bella risposta. Puoi usare il codice PHP senza i tag di inizio e fine su questo sito se la domanda è taggata php (anche il più delle volte è chiara dal contesto della domanda). Se aggiungi due spazi alla fine di una riga vedrai il <br>, quindi non è necessario digitare molto HTML. Spero che questo aiuti, ho modificato un po 'la tua risposta per migliorarla ancora di più.
Hakre,

Grazie per aver menzionato che PHP decodifica l'URL per te. Questo mi evita di cadere in una tana di coniglio.
Cocest,

Ottima risposta -> Non vuoi urldecode () la stringa $ _GET restituita poiché i + saranno convertiti in spazi. Sarebbe sicuro rawurldecode () l'input, tuttavia,
MarcoZen

14

Sì e no.

Il set di caratteri di base di base64 può in alcuni casi scontrarsi con convenzioni tradizionali utilizzate negli URL. Ma molte delle implementazioni di base64 ti consentono di cambiare il set di caratteri per abbinare meglio gli URL o addirittura venire con uno (come quello di Python urlsafe_b64encode()).

Un altro problema che potresti incontrare è il limite della lunghezza dell'URL o piuttosto la mancanza di tale limite. Poiché gli standard non specificano alcuna lunghezza massima, browser, server, librerie e altri software che funzionano con il protocollo HTTP possono definire i propri limiti. Puoi dare un'occhiata a questo articolo: Domande frequenti sul WWW: qual è la lunghezza massima di un URL?


8

È una codifica base64url che puoi provare, è solo l'estensione del codice di joeshmo sopra.

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));
}

Funziona con i dati codificati con JavaBase64.getUrlEncoder().withoutPadding().encodeToString()

4

Non penso che questo sia sicuro perché, ad esempio, il carattere "=" viene utilizzato in Raw Base 64 e viene anche utilizzato per differenziare i parametri dai valori in un HTTP GET.


1

In teoria, sì, purché non superi la lunghezza massima della stringa di query url e / oor per il client o il server.

In pratica, le cose possono diventare un po 'più complicate. Ad esempio, può attivare una HttpRequestValidationException su ASP.NET se il valore contiene un "on" e si lascia nel trailing "==".


non fai menzione di +, /, o = caratteri che rendono gli URL non validi in alcuni casi.
Will Bickford,

0

Per la codifica sicura degli URL, come base64.urlsafe_b64encode(...)in Python il codice seguente, funziona per me al 100%

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

-10

Sì, è sempre sicuro. ovviamente base64 contiene: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= ma una stringa codificata in base64 di solito non ha +. +verrà convertito in uno spazio vuoto, con conseguente stringa decodificata errata. /è sicuro in una coppia di parametri get. =è sempre alla fine della stringa codificata base64 e il lato server può risolvere =direttamente.


Immagino che sia corretto, dato che gli esperimenti che ho fatto con la codifica Base64 (senza codifica URL) hanno avuto successo, ma mi chiedo se ci sia della documentazione che potresti fornire per il backup?
Sean the Bean,

1
dici "sempre sicuro" ma poi dici "di solito non hanno +". Quindi ti stai contraddendo. Il segno + giunge a causare problemi se lo hai nella stringa base64.
Nick Humrich,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.