URL에서 base64로 인코딩 된 문자열 전달


답변:


206

아니요, base64 문자열에는 데이터의 의미를 변경할 수있는 "+", "="및 "/"문자가 포함될 수 있으므로 URL을 인코딩해야합니다. 하위 폴더처럼 보입니다.

유효한 base64 문자는 다음과 같습니다.

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

4
URL 인코딩은 특히 공간을 낭비합니다. 특히 base64 자체는 많은 문자를 사용하지 않습니다.
Michał Górny

21
나는 당신이 무슨 말을하는지 잘 모르겠습니다 .URL 인코딩은 위 목록의 마지막 세 문자를 제외한 모든 문자를 변경하지 않으며 URLS에 다른 의미가 있기 때문에 잘못 해석되지 않도록합니다. base64의 경우도 마찬가지입니다. 원본 데이터는 이진 또는 무엇이든 될 수 있지만 간단한 프로토콜을 사용하여 쉽게 전송할 수있는 형식으로 인코딩됩니다.
Thiyagaraj

3
먼저, 공간으로 변환 될 수 있으므로 '+'도 이스케이프해야합니다. 둘째로, URL에 사용하기에 안전하고 '표준'문자셋에는 사용되지 않는 문자가 최소한 몇 개 있습니다. 특정 상황에서는 전송 된 데이터의 크기를 세 번 늘릴 수도 있습니다. 해당 문자를 다른 문자로 바꾸면 동일한 길이를 유지하면서 트릭을 수행합니다. 그리고 그것은 또한 표준 솔루션입니다.
Michał Górny

8
en.wikipedia.org/wiki/Base64#URL_applications — 이스케이프 처리는 '불필요하게 문자열을 더 길게 만든다'고 대체 문자셋 변형을 언급합니다.
Michał Górny

1
이 답변으로 인해 내 문제를 정확히 언급 한 것으로 진단했습니다. URL 처리로 인해 기본 64 자 (+, /, =) 중 일부가 변경되었습니다. 기본 64 문자열을 URL 인코딩하면 문제가 해결되었습니다.
Chuck Krutsinger

272

추가적인 base64 사양이 있습니다. (자세한 내용은 여기 표를 참조하십시오 ). 그러나 기본적으로 인코딩하려면 65 문자가 필요합니다 : 26 소문자 + 26 대문자 + 10 자리 = 62.

두 개의 [ '+', '/']와 패딩 문자 '='가 더 필요합니다. 그러나 그중 어느 것도 URL 친화적이지 않으므로 다른 문자를 사용 하면 설정됩니다. 위의 차트에서 표준 문자는 [ '-', '_']이지만, 동일한 문자를 해독하고 다른 문자와 공유 할 필요가없는 한 다른 문자를 사용할 수 있습니다.

나는 당신 자신의 도우미를 작성하는 것이 좋습니다. base64_encode 에 대한 PHP 매뉴얼 페이지 의 주석에서 이와 같이 :

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

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

53
URL에서 쉼표가 예약되지 않은 훌륭한 솔루션입니다. '~'(물결표) 또는 '.'를 사용하는 것이 좋습니다. 대신 (점).
kralyk

11
@kralyk : urlencoderodrigo-silveira의 대답에서 제안한대로 사용 하는 것이 좋습니다. URL 길이가 적은 문자를 저장하는 두 가지 새로운 기능을 만드는 것은 문을 사용하는 대신 창을 통과하는 집에 들어가는 것과 같습니다.
Marco Demaio

5
@MarcoDemaio는 어떻게 사용 될지 모른 채 몇 글자라고 말할 수 없습니다. 모든 인코딩 된 문자는 길이가 3 배이며 "+++ ..."가 유효한 base64 문자열이 아닌 이유는 무엇입니까? URL에는 브라우저 제한이 있으며 URL이 3 배가되면 해당 제한에 도달 할 수 있습니다.
leewz

10
@RandalSchwartz 물결표 URL 안전합니다. RFC3986에서 :unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
kralyk

3
,urlencoded되어야하므로 en.wikipedia.org/wiki/Base64#Variants_summary_table 의 유일한 변형 대신에 후행을 유지하는 %2C것이 좋습니다.._--_,
PaulH

75

@joeshmo 또는 도우미 함수를 작성하는 대신 base64로 인코딩 된 문자열을 urlencode 할 수 있습니다. 이것은 도우미 기능과 똑같은 일을하지만 두 가지 추가 기능이 필요하지 않습니다.

$str = 'Some String';

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

2
결과는 정확히 동일하지 않습니다. urlencode는 유효하지 않은 문자를 인코딩하기 위해 3자를 사용하고 joeshmo의 솔루션은 1을 사용합니다. 큰 차이는 아니지만 여전히 낭비입니다.
Josef Borkovec

1
@JosefBorkovec 정말요? 그런 다음 base64-> url-> encoded와 동일한 수의 바이트가 다양한 결과 길이가 될 수 있지만 다른 솔루션은 예측 가능한 길이를 제공합니다.
humanandANDpeace

@humanityANDpeace 예, urlencode는 특정 base64 문자열의 크기를 3 배로 늘리기 때문에 까다로운 솔루션입니다. 출력이 입력보다 크기 때문에 버퍼를 재사용 할 수 없습니다.
Navin

4
1에서 3 자로 확장은 평균 64 자 중 3 자에서 발생하므로 9 %의 오버 헤드 (2 * 3 / 64)
PaulH

/GET 매개 변수가 아닌 URL의 경로로 전달할 경우 문자에 주의하십시오 . /양쪽에 다른 것으로 바꾸지 않으면 경로가 변경됩니다 .
NeverEndingQueue

41

소개 참고 여기에 대한 답변 중 일부가 약간 잘못되어 있기 때문에 약간의 설명을 게시하는 경향이 있습니다.

대답은 NO입니다 . 더하기 부호는 $ _GET 전역 배열 내에서 SPACE로 변환되므로 URL 쿼리 문자열 내에서 base64로 인코딩 된 매개 변수를 전달할 수 없습니다. 즉, test.php? myVar = stringwith + sign 을 보낸 경우

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

결과는 다음과 같습니다.
stringwith sign

이 문제를 해결하는 쉬운 방법 urlencode()은 쿼리 문자열에 base64 문자열을 추가하여 +, = 및 / 문자를 % ## 코드로 이스케이프 처리하는 것입니다. 인스턴스에 대한 urlencode("stringwith+sign")반환stringwith%2Bsign

액션을 처리 할 때 PHP는 $ _GET 전역을 채울 때 쿼리 문자열을 자동으로 디코딩합니다. 예를 들어, test.php? myVar = stringwith % 2Bsign 을 보낸 경우

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

결과는 다음과 같습니다.
stringwith+sign

당신은 할 수 없습니다 원하는 urldecode()+의이 공간으로 변환됩니다으로는 $ _GET 문자열을 반환했습니다.
즉, 동일한 test.php? myVar = stringwith % 2Bsign 을 보낸 경우

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

결과는 예기치 않은 것입니다.
stringwith sign

rawurldecode()입력에 안전 하지만 중복되어 불필요합니다.


1
좋은 대답입니다. 질문에 php 태그가 붙은 경우이 사이트에서 시작 및 끝 태그없이 PHP 코드를 사용할 수 있습니다 (대부분 질문의 맥락에서 명확함). 줄 끝에 공백을 두 개 추가하면을 볼 수 <br>있으므로 HTML을 많이 입력 할 필요가 없습니다. 이것이 도움이되기를 바랍니다. 나는 당신의 대답을 조금 더 향상시키기 위해 약간 편집했습니다.
hakre

PHP가 URL을 해독한다고 언급 해 주셔서 감사합니다. 이렇게하면 토끼 구멍에 빠지지 않습니다.
Cocest

큰 답변-> 반환 된 $ _GET 문자열을 +로 공백으로 변환하므로 urldecode ()하지 않으려 고합니다. 그러나 입력을 rawurldecode ()하는 것이 안전합니다.
MarcoZen

14

예, 아니오

base64의 기본 문자 집합은 경우에 따라 URL에 사용 된 기존 규칙과 충돌 할 수 있습니다. 그러나 많은 base64 구현을 통해 문자 집합을 변경하여 URL을 더 잘 일치 시키거나 Python과 같은 URL을 제공 할 수도 있습니다 urlsafe_b64encode().

직면 할 수있는 또 다른 문제는 URL 길이 제한 또는 그와 같은 제한이 없다는 것입니다. 표준은 최대 길이를 지정하지 않기 때문에 브라우저, 서버, 라이브러리 및 HTTP 프로토콜을 사용하는 기타 소프트웨어는 자체 제한을 정의 할 수 있습니다. 이 문서를 한 번 봐 걸릴 수 있습니다 : WWW FAQ를 :의 URL의 최대 길이 무엇입니까?


8

그것의 base64url 인코딩은 위의 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));
}

이것은 Java로 인코딩 된 데이터에 적용됩니다.Base64.getUrlEncoder().withoutPadding().encodeToString()

4

예를 들어 "="문자는 원시 기본 64에서 사용되며 매개 변수를 HTTP GET의 값과 구별하는 데 사용되기 때문에 이것이 안전하다고 생각하지 않습니다.


1

이론적으로, 클라이언트 또는 서버의 최대 URL 및 / 또는 쿼리 문자열 길이를 초과하지 않는 한 가능합니다.

실제로는 상황이 조금 까다로워 질 수 있습니다. 예를 들어, 값에 "on"이 포함되고 후행 "=="로두면 ASP.NET에서 HttpRequestValidationException을 트리거 할 수 있습니다.


어떤 경우에는 URL을 유효하지 않게하는 +, / 또는 = 문자는 언급하지 않습니다.
Will Bickford

0

base64.urlsafe_b64encode(...)파이썬에서 와 같이 URL 안전 인코딩을 위해 아래 코드는 100 % 나에게 효과적입니다.

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

-10

예, 항상 안전합니다. 물론 base64는 다음을 포함 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= 하지만 base64로 인코딩 된 문자열은 보통 no +입니다. +공백으로 변환되어 잘못된 디코딩 문자열이 생성됩니다. /get 매개 변수 쌍에서 안전합니다. =는 항상 base64로 인코딩 된 문자열의 끝에 있으며 서버 측에서 =직접 확인할 수 있습니다.


URL 인코딩없이 base64 인코딩으로 수행 한 실험이 성공적으로 완료되었으므로 이것이 정확하다고 생각하지만이를 백업하기 위해 제공 할 수있는 문서가 있는지 궁금합니다.
Sean the Bean

1
"항상 안전"이라고 말하지만 "보통 +가 없습니다"라고 말합니다. 당신의 모순입니다. base64 문자열에 + 기호가 있으면 문제를 일으키는 + 기호 이음새입니다.
Nick Humrich
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.