Нет, это не так - связанный вопрос более новый. Так что это делает связанный вопрос дубликатом этого ...
Серж
Ответы:
206
Нет, вам нужно будет его кодировать по URL-адресу, поскольку строки base64 могут содержать символы «+», «=» и «/», которые могут изменить значение ваших данных - они выглядят как подпапка.
URL-кодирование - пустая трата пространства, тем более что само base64 оставляет много символов неиспользованными.
Михал Гурни,
21
Я не уверен, что понимаю, что вы говорите - кодировка URL не изменит никаких символов, кроме последних трех символов в приведенном выше списке, и это предотвратит их неверную интерпретацию, поскольку они имеют другие значения в URL-адресах. То же самое касается base64, исходные данные могут быть двоичными или что-то еще, но они кодируются в форме, которая может быть легко передана с использованием простых протоколов.
Тиягарадж
3
Во-первых, вы также должны экранировать «+», так как он может быть преобразован в пространство. Во-вторых, есть как минимум несколько символов, которые безопасны для использования в URL и не используются в «стандартной» кодировке. Ваш метод может даже увеличить размер передаваемых данных три раза в определенных ситуациях; Заменив эти символы другими, мы добьемся успеха, сохранив ту же длину. И это вполне стандартное решение тоже.
Благодаря этому ответу я поставил диагноз своей проблеме именно так, как она и была упомянута. Некоторые из базовых 64 символов (+, /, =) были изменены из-за обработки URL. Когда я URL закодировал строку base 64, проблема была решена.
Чак Круцингер
272
Есть дополнительные спецификации base64. (Смотрите таблицу здесь для уточнения). Но по сути вам нужно 65 символов для кодирования: 26 строчных + 26 прописных + 10 цифр = 62.
Вам нужно еще два ['+', '/'] и дополнительный символ '='. Но ни один из них не является дружественным к URL, поэтому просто используйте разные символы для них, и все готово. Стандартными из приведенного выше графика являются ['-', '_'], но вы можете использовать другие символы, если вы расшифровали их одинаково, и вам не нужно делиться с другими.
function base64_url_encode($input){return strtr(base64_encode($input),'+/=','._-');}function base64_url_decode($input){return base64_decode(strtr($input,'._-','+/='));}
Отличное решение, за исключением того, что запятая не зарезервирована в URL. Я рекомендую использовать «~» (тильда) или «.» (точка) вместо.
kralyk
11
@kralyk: я рекомендую использовать только то, urlencodeчто предложено ответом Родриго-Силвейры. Создание двух новых функций для сохранения нескольких символов в длине URL, это все равно что войти в свой дом, проходя через окно, а не просто используя дверь.
Марко Демайо
5
@MarcoDemaio, не зная, как он будет использоваться, невозможно сказать, что это всего лишь несколько символов. Каждый закодированный символ будет иметь тройную длину, и почему бы "+++ ..." не быть допустимой строкой base64? URL-адреса имеют ограничения браузера, и утроение URL-адреса может привести к достижению этих ограничений.
Leewz
10
@RandalSchwartz тильды есть URL-сейф. Из RFC3986:unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
@joeshmo Или вместо написания вспомогательной функции, вы можете просто urlencode строки в кодировке base64. Это будет делать то же самое, что и ваша вспомогательная функция, но без необходимости использования двух дополнительных функций.
Результат не совсем то же самое. urlencode использует 3 символа для кодирования недопустимых символов, а решение joeshmo использует 1. Это не большая разница, но это все еще пустая трата времени.
Йозеф Борковец
1
@JosefBorkovec Действительно? Тогда это также будет означать, что одинаковое количество байтов, закодированных base64-> url->, может иметь различную результирующую длину, в то время как другое решение дает предсказуемую длину, верно?
человечествоANDpeace
@humanityANDpeace Да, urlencode - дерьмовое решение, потому что оно утраивает размер некоторых строк base64. Вы также не можете повторно использовать буфер, так как вывод больше, чем ввод.
Навин
4
Расширение с 1 до 3 символов происходит в среднем на 3 из 64 символов, так что это накладные расходы на 9% (2 *
3/64
Будьте осторожны с /символом, если вы передаете его не как параметр GET, а как путь в URL. Это изменит ваш путь, если вы не замените /что-то еще с обеих сторон.
NeverEndingQueue
41
Вводное примечание Я склонен опубликовать несколько разъяснений, поскольку некоторые ответы здесь немного вводят в заблуждение (если не неверно).
Ответ НЕТ , вы не можете просто передать закодированный в base64 параметр в строке запроса URL, поскольку знаки плюс преобразуются в ПРОБЕЛ в глобальном массиве $ _GET. Другими словами, если вы отправили test.php? MyVar = stringwith + sign to
//test.phpprint $_GET['myVar'];
результат будет: stringwith sign
Самый простой способ решить эту проблему - просто urlencode()добавить строку base64 перед добавлением ее в строку запроса, чтобы экранировать символы +, = и / в кодах% ##. Например, urlencode("stringwith+sign")возвращаетstringwith%2Bsign
Когда вы обрабатываете действие, PHP автоматически расшифровывает строку запроса, когда она заполняет глобальную переменную $ _GET. Например, если я отправил test.php? MyVar = stringwith% 2Bsign в
//test.phpprint $_GET['myVar'];
результат будет: stringwith+sign
Вы не хотите urldecode()возвращать строку $ _GET, так как + будут преобразованы в пробелы.
Другими словами, если я отправил тот же test.php? MyVar = stringwith% 2Bsign в
Хороший ответ. Вы можете использовать код PHP без начального и конечного тегов на этом сайте, если вопрос помечен php (также чаще всего это ясно из контекста вопроса). Если вы добавите два пробела в конце строки, вы увидите <br>, поэтому не нужно вводить много HTML. Надеюсь, это поможет, я немного отредактировал ваш ответ, чтобы еще лучше его улучшить.
Хакре
Спасибо, что упомянули, что PHP декодирует URL для вас. Это спасает меня от падения в кроличью нору.
Cocest
Отличный ответ -> Вы не хотите, чтобы urldecode () возвращал строку $ _GET, так как + будет преобразован в пробелы. Впрочем, было бы безопасно использовать rawurldecode () для ввода
MarcoZen
14
Да и нет.
Базовый набор символов base64 может в некоторых случаях вступать в противоречие с традиционными соглашениями, используемыми в URL. Но многие реализации base64 позволяют изменить кодировку, чтобы она лучше соответствовала URL-адресам, или даже поставляются с ней (например, в Python urlsafe_b64encode()).
Другая проблема, с которой вы можете столкнуться, - это ограничение длины URL или, скорее, отсутствие такого ограничения. Поскольку в стандартах не указана максимальная длина, браузеры, серверы, библиотеки и другое программное обеспечение, работающее по протоколу HTTP, могут определять свои собственные ограничения. Вы можете взглянуть на эту статью: Часто задаваемые вопросы WWW: Какова максимальная длина URL?
Это работает для данных, закодированных с помощью JavaBase64.getUrlEncoder().withoutPadding().encodeToString()
4
Я не думаю, что это безопасно, потому что, например, символ "=" используется в raw base 64 и также используется для дифференциации параметров от значений в HTTP GET.
Теоретически, да, если вы не превышаете максимальную длину URL-адреса и / или строки запроса для клиента или сервера.
На практике все может стать немного сложнее. Например, он может вызвать исключение HttpRequestValidationException в ASP.NET, если значение содержит «on» и вы оставляете в конце «==».
Да, это всегда безопасно. конечно base64 содержит:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
но строка в кодировке base64 обычно не имеет +. +будет преобразован в пустое пространство, что приведет к неправильной декодированной строке. /безопасен в паре параметров получения. =всегда находится в конце строки, закодированной в base64, и серверная сторона может разрешить =напрямую.
Я предполагаю, что это правильно, поскольку эксперименты, которые я провел с кодировкой base64 (без URL-кодирования), были успешными, но мне интересно, есть ли какая-нибудь документация, которую вы могли бы предоставить, чтобы поддержать это?
Шон Боб
1
вы говорите «всегда безопасно», но потом говорите «обычно нет +». Так что ты сам себе противоречишь. Знак + сшивается, чтобы вызвать проблемы, если он у вас есть в строке base64.
Ответы:
Нет, вам нужно будет его кодировать по URL-адресу, поскольку строки base64 могут содержать символы «+», «=» и «/», которые могут изменить значение ваших данных - они выглядят как подпапка.
Допустимые символы base64 приведены ниже.
источник
Есть дополнительные спецификации base64. (Смотрите таблицу здесь для уточнения). Но по сути вам нужно 65 символов для кодирования: 26 строчных + 26 прописных + 10 цифр = 62.
Вам нужно еще два ['+', '/'] и дополнительный символ '='. Но ни один из них не является дружественным к URL, поэтому просто используйте разные символы для них, и все готово. Стандартными из приведенного выше графика являются ['-', '_'], но вы можете использовать другие символы, если вы расшифровали их одинаково, и вам не нужно делиться с другими.
Я бы порекомендовал просто написать своих собственных помощников. Как это из комментариев на странице руководства php для base64_encode :
источник
urlencode
что предложено ответом Родриго-Силвейры. Создание двух новых функций для сохранения нескольких символов в длине URL, это все равно что войти в свой дом, проходя через окно, а не просто используя дверь.unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
,
должен быть urlencoded к%2C
, я предлагаю использовать._-
вместо-_,
единственного варианта в en.wikipedia.org/wiki/Base64#Variants_summary_table, который сохраняет трейлинг =@joeshmo Или вместо написания вспомогательной функции, вы можете просто urlencode строки в кодировке base64. Это будет делать то же самое, что и ваша вспомогательная функция, но без необходимости использования двух дополнительных функций.
источник
/
символом, если вы передаете его не как параметр GET, а как путь в URL. Это изменит ваш путь, если вы не замените/
что-то еще с обеих сторон.Ответ НЕТ , вы не можете просто передать закодированный в base64 параметр в строке запроса URL, поскольку знаки плюс преобразуются в ПРОБЕЛ в глобальном массиве $ _GET. Другими словами, если вы отправили test.php? MyVar = stringwith + sign to
результат будет:
stringwith sign
Самый простой способ решить эту проблему - просто
urlencode()
добавить строку base64 перед добавлением ее в строку запроса, чтобы экранировать символы +, = и / в кодах% ##. Например,urlencode("stringwith+sign")
возвращаетstringwith%2Bsign
Когда вы обрабатываете действие, PHP автоматически расшифровывает строку запроса, когда она заполняет глобальную переменную $ _GET. Например, если я отправил test.php? MyVar = stringwith% 2Bsign в
результат будет:
stringwith+sign
Вы не хотите
urldecode()
возвращать строку $ _GET, так как + будут преобразованы в пробелы.Другими словами, если я отправил тот же test.php? MyVar = stringwith% 2Bsign в
результат неожиданный:
stringwith sign
Это было бы безопасно для
rawurldecode()
ввода, однако, это было бы излишним и, следовательно, ненужным.источник
<br>
, поэтому не нужно вводить много HTML. Надеюсь, это поможет, я немного отредактировал ваш ответ, чтобы еще лучше его улучшить.Да и нет.
Базовый набор символов base64 может в некоторых случаях вступать в противоречие с традиционными соглашениями, используемыми в URL. Но многие реализации base64 позволяют изменить кодировку, чтобы она лучше соответствовала URL-адресам, или даже поставляются с ней (например, в Python
urlsafe_b64encode()
).Другая проблема, с которой вы можете столкнуться, - это ограничение длины URL или, скорее, отсутствие такого ограничения. Поскольку в стандартах не указана максимальная длина, браузеры, серверы, библиотеки и другое программное обеспечение, работающее по протоколу HTTP, могут определять свои собственные ограничения. Вы можете взглянуть на эту статью: Часто задаваемые вопросы WWW: Какова максимальная длина URL?
источник
Это кодировка base64url, которую вы можете попробовать, это просто расширение кода Joeshmo, описанного выше.
источник
Base64.getUrlEncoder().withoutPadding().encodeToString()
Я не думаю, что это безопасно, потому что, например, символ "=" используется в raw base 64 и также используется для дифференциации параметров от значений в HTTP GET.
источник
Теоретически, да, если вы не превышаете максимальную длину URL-адреса и / или строки запроса для клиента или сервера.
На практике все может стать немного сложнее. Например, он может вызвать исключение HttpRequestValidationException в ASP.NET, если значение содержит «on» и вы оставляете в конце «==».
источник
Для безопасного URL-кодирования, как
base64.urlsafe_b64encode(...)
в Python код ниже, работает для меня на 100%источник
Да, это всегда безопасно. конечно base64 содержит:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
но строка в кодировке base64 обычно не имеет+
.+
будет преобразован в пустое пространство, что приведет к неправильной декодированной строке./
безопасен в паре параметров получения.=
всегда находится в конце строки, закодированной в base64, и серверная сторона может разрешить=
напрямую.источник