URL'de base64 kodlu dizeleri geçirme


Yanıtlar:


206

Hayır, url kodlaması yapmanız gerekir, çünkü base64 dizeleri verilerinizin anlamını değiştirebilecek "+", "=" ve "/" karakterlerini içerebilir - bir alt klasör gibi görünür.

Geçerli base64 karakterleri aşağıda.

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

4
URLencoding, özellikle base64'ün kendisi birçok karakteri kullanılmadığı için alan kaybıdır.
Michał Górny

21
Ne dediğini anladığımdan emin değilim - URL kodlaması, yukarıdaki listede yer alan son üç karakter dışında herhangi bir karakteri değiştirmeyecek ve bu, URL'lerde başka anlamları olduğu için yanlış yorumlanmalarını önlemek. Aynı şey base64 için de geçerlidir, orijinal veriler ikili veya herhangi bir şey olabilir, ancak basit protokoller kullanılarak kolayca iletilebilen bir biçimde kodlanır.
Thiyagaraj

3
İlk olarak, uzaya dönüştürülebileceği için '+' işaretinden de kaçmalısınız. İkinci olarak, URL'lerde kullanım için güvenli olan ve 'standart' karakter kümesinde kullanılmayan en az birkaç karakter vardır. Metodunuz , belirli durumlarda aktarılan verilerin boyutunu üç kez artırabilir ; bu karakterleri başka bir karakterle değiştirmek, aynı uzunluğu koruyarak hile yapacaktır. Ve bu da oldukça standart bir çözüm.
Michał Górny

8
en.wikipedia.org/wiki/Base64#URL_applications - 'kaçmanın ipi gereksiz yere uzattığını' ve alternatif karakter kümesi değişkeninden bahsettiği açıkça belirtiliyor.
Michał Górny

1
Bu cevap nedeniyle, sorunumu tam olarak bahsettiği şey olarak teşhis ettim. Temel 64 karakterden bazıları (+, /, =) URL işleme nedeniyle değiştiriliyordu. URL 64 temel dize kodladığında, sorun çözüldü.
Chuck Krutsinger

272

Ek base64 özellikleri var. (Tabloya bakın burada kesin bilgi için). Ama aslında kodlamak için 65 karaktere ihtiyacınız var: 26 küçük harf + 26 büyük harf + 10 basamak = 62.

İki tane daha ['+', '/'] ve bir dolgu karakteri '=' gerekir. Ama hiçbiri url dostu değil, bu yüzden onlar için farklı karakterler kullanın ve hazırsınız. Yukarıdaki grafikten standart olanlar ['-', '_'], ancak aynı kodları çözdüğünüz sürece başka karakterleri de kullanabilirsiniz ve başkalarıyla paylaşmanız gerekmez.

Sadece kendi yardımcılarını yazmanı tavsiye ederim. Base64_encode için php kılavuz sayfasındaki yorumlar gibi :

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

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

53
URL'lerde virgül kullanılmamışsa harika bir çözüm. '~' (Tilde) veya '' kullanmanızı öneririm. (nokta) yerine.
kralyk

11
@kralyk: Sadece urlencoderodrigo-silveira'nın cevabının önerdiği şekilde kullanmanızı öneririm. Url uzunluğunda birkaç karakter kaydetmek için iki yeni işlev oluşturmak, sadece kapıyı kullanmak yerine pencereden geçen evinize girmek gibidir.
Marco Demaio

5
@MarcoDemaio, nasıl kullanılacağını bilmeden, sadece birkaç karakter olduğunu söylemek imkansız. Her kodlanmış karakter üç kat uzunluğa sahip olacak ve neden "+++ ..." geçerli bir base64 dizesi olmasın? URL'lerin tarayıcı sınırları vardır ve bir URL'yi üç katına çıkarmak bu sınırlara ulaşmanıza neden olabilir.
leewz

10
@RandalSchwartz tilde is URL güvenli. unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
RFC3986

3
Yana ,üzere urlencoded edilmelidir %2C, ben kullanmanızı öneririz ._- yerine -_,tek varyantı gibi en.wikipedia.org/wiki/Base64#Variants_summary_table = sondaki tutar
PaulH

75

@joeshmo Veya bir yardımcı işlev yazmak yerine, base64 kodlu dizeyi urlencode edebilirsiniz. Bu, yardımcı fonksiyonunuzla aynı şeyi yapar, ancak iki ekstra fonksiyona ihtiyaç duymaz.

$str = 'Some String';

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

2
Sonuç tam olarak aynı değildir. urlencode geçerli olmayan karakterleri kodlamak için 3 karakter ve joeshmo'nun çözüm 1'i kullanır. Bu büyük bir fark değil, ama yine de bir israf.
Josef Borkovec

1
@JosefBorkovec Gerçekten mi? O zaman bu aynı zamanda, baz64-> url-> kodlanmış aynı bayt sayısının farklı sonuçta elde edilen çeşitli uzunluklar olabileceği anlamına gelirken, diğer çözüm öngörülebilir bir uzunluk verir, değil mi?
humanityANDpeace

@ insanlıkANDpeace Evet, urlencode boktan bir çözüm çünkü bazı base64 dizelerinin boyutunu üç katına çıkarıyor. Çıktı girişten daha büyük olduğundan arabelleği yeniden kullanamazsınız.
Navin

4
1 ila 3 karakter arasında genişleme, ortalama 64 karakterden
3'ünde gerçekleşir

/Bir GET parametresi olarak değil, URL'de bir yol olarak iletirseniz , karaktere dikkat edin . Her /iki tarafta başka bir şeyle değiştirmezseniz yolunuzu değiştirecektir .
NeverEndingQueue

41

Giriş Notu Buradaki bazı cevaplar biraz yanıltıcı olduğu için (yanlış değilse) birkaç açıklama yapmaya meyilliyim.

Cevap HAYIR , artı işaretleri $ _GET global dizisi içindeki bir SPACE değerine dönüştürüldüğünden, bir URL sorgu dizesine base64 kodlu bir parametre iletemezsiniz. Başka bir deyişle, test.php? MyVar = stringwith + sign to

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

sonuç şöyle olur:
stringwith sign

Bunu çözmenin kolay yolu urlencode(),% ,# kodlarına +, = ve / karakterlerinden kaçmak için sorgu dizesine eklemeden önce base64 dizenizi basitçe belirlemektir . Örneğin, için urlencode("stringwith+sign")getirilerstringwith%2Bsign

Eylemi işlediğinizde PHP, $ _GET global öğesini doldurduğunda sorgu dizesinin kodunu otomatik olarak çözer. Örneğin, test.php? MyVar =% 2Bsign ile dize gönderirsem

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

sonuç:
stringwith+sign

Sen do not istiyorum urldecode()+ 'ın boşluk dönüştürülecektir olarak $ _GET dize döndü.
Bir başka deyişle aynı gönderilen eğer test.php? MyVar = stringwith% 2Bsign için

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

sonuç beklenmedik bir sonuçtur:
stringwith sign

rawurldecode()Girdi için güvenli olabilir , ancak gereksiz ve dolayısıyla gereksiz olacaktır.


1
Güzel cevap. Soru php olarak etiketlenmişse PHP kodunu bu sitede başlangıç ​​ve bitiş etiketleri olmadan kullanabilirsiniz (ayrıca çoğunlukla sorunun bağlamından da anlaşılır). Bir satırın sonuna iki boşluk eklerseniz <br>, çok fazla HTML yazmanıza gerek kalmaz. Umarım bu yardımcı olur, cevabınızı daha da geliştirmek için biraz düzenledim.
hakre

PHP'nin URL'yi sizin için çözdüğünden bahsettiğiniz için teşekkür ederiz. Bu beni bir tavşan deliğine düşmekten kurtarıyor.
Cocest

Harika Yanıt -> + 's boşluklara dönüştürüleceğinden, döndürülen $ _GET dizesini urldecode () yapmak istemezsiniz. Ancak, girişi rawurldecode () güvenli olurdu,
MarcoZen

14

Evet ve hayır.

Base64'ün temel karakter dizisi bazı durumlarda URL'lerde kullanılan geleneksel sözleşmelerle çakışabilir. Ancak base64 uygulamalarının çoğu, URL'yi daha iyi eşleştirmek veya hatta biriyle (Python'lar gibi urlsafe_b64encode()) eşleştirmek için karakter kümesini değiştirmenize olanak tanır .

Karşılaşabileceğiniz bir diğer sorun URL uzunluğu sınırı veya daha doğrusu - bu tür bir sınırın olmamasıdır. Standartlar herhangi bir maksimum uzunluk belirtmediği için, tarayıcılar, sunucular, kütüphaneler ve HTTP protokolüyle çalışan diğer yazılımlar kendi sınırlarını tanımlayabilir. Bu makaleye göz atabilirsiniz: WWW SSS: Bir URL'nin maksimum uzunluğu nedir?


8

Onun deneyebileceğiniz bir base64url kodlaması, yukarıdaki joeshmo kodunun sadece uzantısı.

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

Bu Java ile kodlanan veriler için çalışırBase64.getUrlEncoder().withoutPadding().encodeToString()

4

Bunun güvenli olduğunu düşünmüyorum çünkü örneğin "=" karakteri ham taban 64'te kullanılıyor ve parametreleri HTTP GET'teki değerlerden ayırmada da kullanılıyor.


1

Teoride, istemci veya sunucu için maksimum URL ve / veya sorgu dizesi uzunluğunu aşmadığınız sürece evet.

Pratikte, işler biraz daha hileli olabilir. Örneğin, değer bir "açık" içeriyorsa ve "==" izinden ayrılırsanız ASP.NET üzerinde bir HttpRequestValidationException tetikleyebilir.


belirli durumlarda URL'leri geçersiz kılan +, / veya = karakterlerinden bahsetmezsiniz.
Will Bickford

0

Url güvenli kodlama için, base64.urlsafe_b64encode(...)aşağıdaki kodda olduğu gibi,% 100 için bana çalışır

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

-10

Evet, her zaman güvenlidir. Tabii ki base64 şunları içerir: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= ancak base64 kodlu bir dizede genellikle hayır vardır +. +boş bir alana dönüştürülecek ve yanlış kod çözme dizesine neden olacaktır. /get parametreleri çiftinde güvenlidir. =her zaman base64 kodlu dizenin sonundadır ve sunucu tarafı =doğrudan çözülebilir .


Base64 kodlaması (url kodlaması olmadan) ile yaptığım deneyler başarılı olduğundan, bunun doğru olduğunu tahmin ediyorum, ama bunu yedeklemek için sağlayabileceğiniz herhangi bir belge olup olmadığını merak ediyorum?
Sean the Bean

1
"her zaman güvenli" diyorsunuz ama sonra "genellikle + yok" diyorsunuz. Yani kendinle çelişiyorsun. Base64 dizenizde varsa, + işareti dikişlere sorun çıkarır.
Nick Humrich
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.