Nie, nie - powiązane pytanie jest nowsze. Czyni to powiązane pytanie duplikatem tego ...
sierżę
Odpowiedzi:
206
Nie, musisz go zakodować, ponieważ ciągi base64 mogą zawierać znaki „+”, „=” i „/”, które mogą zmieniać znaczenie twoich danych - wyglądają jak podfolder.
Kodowanie adresów URL to strata miejsca, zwłaszcza że sama baza64 pozostawia wiele znaków nieużywanych.
Michał Górny,
21
Nie jestem pewien, czy rozumiem, co mówisz - kodowanie adresów URL nie zmieni żadnego ze znaków poza trzema ostatnimi znakami z powyższej listy, a to zapobiegnie ich nieprawidłowej interpretacji, ponieważ mają one inne znaczenie w adresach URL. To samo dotyczy base64, oryginalne dane mogą być binarne lub cokolwiek, ale są zakodowane w formie, którą można łatwo przesłać za pomocą prostych protokołów.
Thiyagaraj
3
Po pierwsze, powinieneś także uciec od znaku „+”, ponieważ może on zostać przekształcony w przestrzeń. Po drugie, istnieje co najmniej kilka znaków, które można bezpiecznie używać w adresach URL i nie są one używane w „standardowym” zestawie znaków. Twoja metoda może nawet trzykrotnie zwiększyć rozmiar przesyłanych danych w niektórych sytuacjach; zastępując te postacie innymi, załatwi sprawę, zachowując tę samą długość. Jest to również dość standardowe rozwiązanie.
Z powodu tej odpowiedzi zdiagnozowałem mój problem jako dokładnie to, o czym wspomniałem. Niektóre podstawowe 64 znaki (+, /, =) były zmieniane z powodu przetwarzania adresów URL. Gdy kodowałem adres URL podstawowego ciągu 64, problem został rozwiązany.
Chuck Krutsinger
272
Istnieją dodatkowe specyfikacje base64. (Szczegóły podano w tabeli tutaj ). Ale zasadniczo potrzebujesz 65 znaków do zakodowania: 26 małych liter + 26 wielkich liter + 10 cyfr = 62.
Potrzebujesz jeszcze dwóch ['+', '/'] i padding char '='. Ale żaden z nich nie jest przyjazny dla adresów URL, więc po prostu użyj dla nich różnych znaków i gotowe. Standardowe z powyższej tabeli to ['-', '_'], ale możesz używać innych znaków, o ile dekodujesz je tak samo i nie musisz dzielić się z innymi.
function base64_url_encode($input){return strtr(base64_encode($input),'+/=','._-');}function base64_url_decode($input){return base64_decode(strtr($input,'._-','+/='));}
Świetne rozwiązanie, z wyjątkiem przecinków w adresach URL. Polecam użycie „~” (tylda) lub „.” (kropka) zamiast.
kralyk
11
@kralyk: Polecam po prostu, urlencodejak sugeruje odpowiedź rodrigo-silveira. Utworzenie dwóch nowych funkcji w celu zaoszczędzenia kilku znaków w adresie URL to jak wejście do domu przez okno zamiast po prostu korzystania z drzwi.
Marco Demaio
5
@MarcoDemaio, nie wiedząc, jak zostanie użyty, nie można powiedzieć, że to tylko kilka znaków. Każdy zakodowany znak będzie miał potrójną długość i dlaczego „+++ ...” nie byłby prawidłowym ciągiem base64? Adresy URL mają ograniczenia przeglądarki, a trzykrotny URL może spowodować, że je przekroczysz.
leewz
10
@RandalSchwartz tylda jest bezpieczna pod adresem URL. Z RFC3986:unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
@joeshmo Lub zamiast pisać funkcję pomocnika, możesz po prostu urlencode kodowany ciąg base64. To zrobiłoby dokładnie to samo, co funkcja pomocnika, ale bez potrzeby dwóch dodatkowych funkcji.
Wynik nie jest dokładnie taki sam. urlencode używa 3 znaków do kodowania nieważnych znaków, a rozwiązanie joeshmo używa 1. To nie jest duża różnica, ale to wciąż marnotrawstwo.
Josef Borkovec
1
@JosefBorkovec Naprawdę? Oznaczałoby to również, że zakodowana ta sama liczba bajtów base64-> url-> może mieć różną różną wynikową długość, podczas gdy inne rozwiązanie daje przewidywalną długość, prawda?
humanityANDpeace
@humanityANDpeace Tak, urlencode jest gównianym rozwiązaniem, ponieważ trzykrotnie zwiększa rozmiar niektórych ciągów base64. Nie można również ponownie użyć bufora, ponieważ dane wyjściowe są większe niż dane wejściowe.
Navin
4
Rozszerzenie od 1 do 3 znaków występuje średnio na 3 z 64 znaków, więc jest to 9% narzut (2 *
3/64
Uważaj na /znak, jeśli przekazujesz go nie jako parametr GET, ale jako ścieżkę w adresie URL. Zmieni to twoją ścieżkę, jeśli nie zastąpisz /czegoś innego po obu stronach.
NeverEndingQueue,
41
Uwaga wstępna Skłaniam się do opublikowania kilku wyjaśnień, ponieważ niektóre z odpowiedzi tutaj były nieco mylące (jeśli nie nieprawidłowe).
Odpowiedź brzmi NIE , nie można po prostu przekazać parametru zakodowanego w base64 w ciągu zapytania do adresu URL, ponieważ znaki plus są konwertowane na SPACJĘ w globalnej tablicy $ _GET. Innymi słowy, jeśli wysłałeś test.php? MyVar = stringwith + sign to
//test.phpprint $_GET['myVar'];
wynik byłby: stringwith sign
Łatwym sposobem rozwiązania tego jest po prostu urlencode()ciąg base64 przed dodaniem go do ciągu zapytania, aby uciec od znaków +, = i / do kodów% ##. Na przykład urlencode("stringwith+sign")zwracastringwith%2Bsign
Podczas przetwarzania akcji PHP automatycznie dekoduje ciąg zapytania, gdy zapełni on globalną wartość $ _GET. Na przykład, jeśli wysłałem test.php? MyVar = stringwith% 2Bsign to
//test.phpprint $_GET['myVar'];
wynikiem byłoby: stringwith+sign
Zdajesz nie chcą urldecode()zwrócony ciąg $ _GET jak s + 'zostaną zamienione na spacje.
Innymi słowy, jeśli wysłałem ten sam test.php? MyVar = stringwith% 2Bsign to
Niezła odpowiedź. Możesz użyć kodu PHP bez początkowych i końcowych znaczników na tej stronie, jeśli pytanie jest oznaczone php (również najczęściej wynika to z kontekstu pytania). Jeśli dodasz dwie spacje na końcu linii, zobaczysz <br>, więc nie musisz pisać dużo HTML. Mam nadzieję, że to pomoże. Zredagowałem trochę twoją odpowiedź, aby jeszcze bardziej ją poprawić.
hakre
Dziękujemy za wspomnienie, że PHP dekoduje dla ciebie adres URL. To ratuje mnie przed wpadnięciem do króliczej nory.
Cocest,
Świetna odpowiedź -> Nie chcesz urldecode () zwracanego ciągu $ _GET, ponieważ znaki + zostaną przekonwertowane na spacje. Bezpiecznie byłoby jednak wprowadzić kod źródłowy rawurld ()
MarcoZen
14
Tak i nie.
Podstawowy zestaw znaków base64 może w niektórych przypadkach kolidować z tradycyjnymi konwencjami stosowanymi w adresach URL. Jednak wiele implementacji base64 pozwala na zmianę zestawu znaków w celu lepszego dopasowania adresów URL lub nawet dostarczenia go z jednym (np. Pythona urlsafe_b64encode()).
Innym problemem, z którym możesz się spotkać, jest limit długości adresu URL, a raczej jego brak. Ponieważ standardy nie określają maksymalnej długości, przeglądarki, serwery, biblioteki i inne oprogramowanie współpracujące z protokołem HTTP mogą określać własne ograniczenia. Możesz rzucić okiem na ten artykuł: Często zadawane pytania na temat WWW: Jaka jest maksymalna długość adresu URL?
Działa to w przypadku danych zakodowanych w JavieBase64.getUrlEncoder().withoutPadding().encodeToString()
4
Nie sądzę, że jest to bezpieczne, ponieważ np. Znak „=” jest używany w surowej bazie 64 i jest także używany do odróżniania parametrów od wartości w HTTP GET.
Teoretycznie tak, o ile nie przekroczysz maksymalnej długości ciągu adresu URL i / lub zapytania dla klienta lub serwera.
W praktyce może być trochę trudniej. Na przykład może wywołać wyjątek HttpRequestValidationException na platformie ASP.NET, jeśli wartość zawiera „on”, a ty zostawisz końcowe „==”.
Tak, zawsze jest bezpiecznie. oczywiście base64 zawiera:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
ale łańcuch zakodowany base64 zwykle nie ma +. +zostanie przekonwertowany na puste miejsce, co spowoduje nieprawidłowy dekodowanie ciągu. /jest bezpieczny w parze parametrów get. =jest zawsze na końcu łańcucha zakodowanego w base64, a strona serwera może rozwiązać =bezpośrednio.
Zgaduję, że jest to poprawne, ponieważ eksperymenty, które przeprowadziłem z kodowaniem base64 (bez kodowania adresu URL) zakończyły się powodzeniem, ale zastanawiam się, czy jest jakaś dokumentacja, którą mógłbyś dostarczyć, aby to zrobić?
Sean the Bean
1
mówisz „zawsze bezpieczny”, ale potem mówisz „zwykle nie ma +”. Więc zaprzeczasz sobie. Szwy + powodują problemy, jeśli masz je w ciągu base64.
Odpowiedzi:
Nie, musisz go zakodować, ponieważ ciągi base64 mogą zawierać znaki „+”, „=” i „/”, które mogą zmieniać znaczenie twoich danych - wyglądają jak podfolder.
Prawidłowe znaki base64 są poniżej.
źródło
Istnieją dodatkowe specyfikacje base64. (Szczegóły podano w tabeli tutaj ). Ale zasadniczo potrzebujesz 65 znaków do zakodowania: 26 małych liter + 26 wielkich liter + 10 cyfr = 62.
Potrzebujesz jeszcze dwóch ['+', '/'] i padding char '='. Ale żaden z nich nie jest przyjazny dla adresów URL, więc po prostu użyj dla nich różnych znaków i gotowe. Standardowe z powyższej tabeli to ['-', '_'], ale możesz używać innych znaków, o ile dekodujesz je tak samo i nie musisz dzielić się z innymi.
Polecam po prostu napisać własnych pomocników. Podobnie jak w komentarzach na stronie podręcznika php dla base64_encode :
źródło
urlencode
jak sugeruje odpowiedź rodrigo-silveira. Utworzenie dwóch nowych funkcji w celu zaoszczędzenia kilku znaków w adresie URL to jak wejście do domu przez okno zamiast po prostu korzystania z drzwi.unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
,
należy to zaadresować%2C
, sugeruję użycie._-
zamiast-_,
jak jedynego wariantu w en.wikipedia.org/wiki/Base64#Variants_summary_table, który utrzymuje końcowy =@joeshmo Lub zamiast pisać funkcję pomocnika, możesz po prostu urlencode kodowany ciąg base64. To zrobiłoby dokładnie to samo, co funkcja pomocnika, ale bez potrzeby dwóch dodatkowych funkcji.
źródło
/
znak, jeśli przekazujesz go nie jako parametr GET, ale jako ścieżkę w adresie URL. Zmieni to twoją ścieżkę, jeśli nie zastąpisz/
czegoś innego po obu stronach.Odpowiedź brzmi NIE , nie można po prostu przekazać parametru zakodowanego w base64 w ciągu zapytania do adresu URL, ponieważ znaki plus są konwertowane na SPACJĘ w globalnej tablicy $ _GET. Innymi słowy, jeśli wysłałeś test.php? MyVar = stringwith + sign to
wynik byłby:
stringwith sign
Łatwym sposobem rozwiązania tego jest po prostu
urlencode()
ciąg base64 przed dodaniem go do ciągu zapytania, aby uciec od znaków +, = i / do kodów% ##. Na przykładurlencode("stringwith+sign")
zwracastringwith%2Bsign
Podczas przetwarzania akcji PHP automatycznie dekoduje ciąg zapytania, gdy zapełni on globalną wartość $ _GET. Na przykład, jeśli wysłałem test.php? MyVar = stringwith% 2Bsign to
wynikiem byłoby:
stringwith+sign
Zdajesz nie chcą
urldecode()
zwrócony ciąg $ _GET jak s + 'zostaną zamienione na spacje.Innymi słowy, jeśli wysłałem ten sam test.php? MyVar = stringwith% 2Bsign to
wynik jest nieoczekiwany:
stringwith sign
Byłby bezpieczny dla
rawurldecode()
danych wejściowych, jednak byłby zbędny, a zatem niepotrzebny.źródło
<br>
, więc nie musisz pisać dużo HTML. Mam nadzieję, że to pomoże. Zredagowałem trochę twoją odpowiedź, aby jeszcze bardziej ją poprawić.Tak i nie.
Podstawowy zestaw znaków base64 może w niektórych przypadkach kolidować z tradycyjnymi konwencjami stosowanymi w adresach URL. Jednak wiele implementacji base64 pozwala na zmianę zestawu znaków w celu lepszego dopasowania adresów URL lub nawet dostarczenia go z jednym (np. Pythona
urlsafe_b64encode()
).Innym problemem, z którym możesz się spotkać, jest limit długości adresu URL, a raczej jego brak. Ponieważ standardy nie określają maksymalnej długości, przeglądarki, serwery, biblioteki i inne oprogramowanie współpracujące z protokołem HTTP mogą określać własne ograniczenia. Możesz rzucić okiem na ten artykuł: Często zadawane pytania na temat WWW: Jaka jest maksymalna długość adresu URL?
źródło
Jest to kod base64url, który możesz wypróbować, to tylko rozszerzenie powyższego kodu joeshmo.
źródło
Base64.getUrlEncoder().withoutPadding().encodeToString()
Nie sądzę, że jest to bezpieczne, ponieważ np. Znak „=” jest używany w surowej bazie 64 i jest także używany do odróżniania parametrów od wartości w HTTP GET.
źródło
Teoretycznie tak, o ile nie przekroczysz maksymalnej długości ciągu adresu URL i / lub zapytania dla klienta lub serwera.
W praktyce może być trochę trudniej. Na przykład może wywołać wyjątek HttpRequestValidationException na platformie ASP.NET, jeśli wartość zawiera „on”, a ty zostawisz końcowe „==”.
źródło
Dla bezpiecznego
base64.urlsafe_b64encode(...)
kodu URL, jak w Pythonie poniższy kod działa dla mnie w 100%źródło
Tak, zawsze jest bezpiecznie. oczywiście base64 zawiera:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
ale łańcuch zakodowany base64 zwykle nie ma+
.+
zostanie przekonwertowany na puste miejsce, co spowoduje nieprawidłowy dekodowanie ciągu./
jest bezpieczny w parze parametrów get.=
jest zawsze na końcu łańcucha zakodowanego w base64, a strona serwera może rozwiązać=
bezpośrednio.źródło