จะปลอดภัยไหมที่จะส่งสตริงเบสที่เข้ารหัสแบบ raw64 ผ่านพารามิเตอร์ GET?
จะปลอดภัยไหมที่จะส่งสตริงเบสที่เข้ารหัสแบบ raw64 ผ่านพารามิเตอร์ GET?
คำตอบ:
ไม่คุณจะต้องเข้ารหัส url เนื่องจากสตริง base64 สามารถมีอักขระ "+", "=" และ "/" ซึ่งสามารถเปลี่ยนความหมายของข้อมูลของคุณ - ดูเหมือนโฟลเดอร์ย่อย
base64 อักขระที่ถูกต้องอยู่ด้านล่าง
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
มีคุณสมบัติเพิ่มเติม base64 (ดูตารางที่นี่สำหรับข้อมูลเฉพาะ) แต่โดยพื้นฐานแล้วคุณต้องการ 65 ตัวอักษรเพื่อเข้ารหัส: 26 ตัวพิมพ์เล็ก + 26 ตัวพิมพ์ใหญ่ + 10 หลัก = 62
คุณต้องการอีกสอง [+ +, '/'] และ padding char '=' แต่ไม่มีของพวกเขาที่เป็นมิตรกับ url ดังนั้นเพียงใช้ตัวอักษรที่แตกต่างกันสำหรับพวกเขาและคุณตั้ง มาตรฐานจากแผนภูมิด้านบนคือ ['-', '_'] แต่คุณสามารถใช้ตัวอักษรอื่นได้ตราบใดที่คุณถอดรหัสพวกมันเหมือนกันและไม่จำเป็นต้องแบ่งปันกับคนอื่น
ฉันขอแนะนำเพียงแค่เขียนผู้ช่วยของคุณเอง เช่นนี้จากความคิดเห็นในหน้าคู่มือ php สำหรับ base64_encode :
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '._-');
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '._-', '+/='));
}
urlencode
ตามคำแนะนำของคำตอบของ rodrigo-silveira การสร้างฟังก์ชั่นใหม่สองฟังก์ชั่นเพื่อประหยัด chars สองสามตัวในความยาว url เหมือนเข้ามาในบ้านของคุณผ่านหน้าต่างแทนที่จะใช้เพียงประตู
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
,
ควร urlencoded เป็น%2C
ฉันขอแนะนำให้ใช้._-
แทนที่จะ-_,
เป็นตัวแปรตัวเดียวในen.wikipedia.org/wiki/Base64#Variants_summary_tableที่คอยตามมา =
@ joeshmo หรือแทนที่จะเขียนฟังก์ชั่นตัวช่วยคุณสามารถ urlencode สตริงที่เข้ารหัส base64 สิ่งนี้จะทำสิ่งเดียวกันกับฟังก์ชั่นตัวช่วยของคุณ แต่ไม่จำเป็นต้องใช้ฟังก์ชั่นพิเศษอีกสองอย่าง
$str = 'Some String';
$encoded = urlencode( base64_encode( $str ) );
$decoded = base64_decode( urldecode( $encoded ) );
/
ตัวละครถ้าคุณผ่านมันไม่ได้เป็นพารามิเตอร์ GET แต่เป็นเส้นทางใน URL มันจะเปลี่ยนเส้นทางของคุณหากคุณไม่ได้แทนที่/
ด้วยอย่างอื่นทั้งสองด้าน
บันทึกย่อเบื้องต้นฉันมีแนวโน้มที่จะโพสต์คำอธิบายเล็ก ๆ น้อย ๆ เนื่องจากคำตอบบางส่วนของที่นี่เป็นการหลอกลวงเล็กน้อย (หากไม่ถูกต้อง)
คำตอบคือไม่คุณไม่สามารถส่งพารามิเตอร์ base64 ที่เข้ารหัสได้ภายในสตริงการสืบค้น URL เนื่องจากเครื่องหมายบวกจะถูกแปลงเป็น SPACE ภายในอาร์เรย์ส่วนกลางของ $ _GET กล่าวอีกนัยหนึ่งถ้าคุณส่งtest.php? myVar = stringwith + sign to
//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()
การป้อนข้อมูล แต่มันจะซ้ำซ้อนและดังนั้นจึงไม่จำเป็น
<br>
ดังนั้นไม่จำเป็นต้องพิมพ์ HTML มาก ฉันหวังว่านี่จะช่วยฉันแก้ไขคำตอบของคุณเล็กน้อยเพื่อปรับปรุงให้ดียิ่งขึ้น
ใช่และไม่.
ชุดอักขระพื้นฐานของ base64 ในบางกรณีอาจขัดแย้งกับแบบแผนดั้งเดิมที่ใช้ใน URL แต่การใช้งาน base64 จำนวนมากทำให้คุณสามารถเปลี่ยนชุดอักขระเพื่อให้ตรงกับ URL ที่ดีขึ้นหรือแม้กระทั่งมาพร้อมกับหนึ่ง (เช่น Python urlsafe_b64encode()
)
ปัญหาอื่นที่คุณอาจประสบคือขีดจำกัดความยาวของ URL หรือมากกว่า - ไม่มีข้อ จำกัด ดังกล่าว เนื่องจากมาตรฐานไม่ได้ระบุความยาวสูงสุดเบราว์เซอร์เซิร์ฟเวอร์ไลบรารีและซอฟต์แวร์อื่น ๆ ที่ทำงานกับโปรโตคอล HTTP อาจกำหนดขีด จำกัด ของตัวเอง คุณอาจดูที่บทความนี้: คำถามที่พบบ่อย WWW: ความยาวสูงสุดของ URL คืออะไร?
มันเป็น base64url encode ที่คุณสามารถลองใช้ได้เพียงแค่ขยายโค้ดของ 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));
}
ฉันไม่คิดว่าจะปลอดภัยเพราะเช่นตัวอักษร "=" ใช้ในฐาน 64 และยังใช้ในการแยกความแตกต่างของพารามิเตอร์จากค่าใน HTTP GET
ในทางทฤษฎีใช่ตราบใดที่คุณไม่เกินความยาวสูงสุดของสตริงข้อความค้นหา / url สำหรับไคลเอ็นต์หรือเซิร์ฟเวอร์
ในทางปฏิบัติสิ่งต่าง ๆ อาจมีความยุ่งยากเล็กน้อย ตัวอย่างเช่นมันสามารถทริกเกอร์ HttpRequestValidationException บน ASP.NET หากค่าเกิดขึ้นเพื่อให้มี "on" และคุณปล่อยไว้ในส่วนท้าย "=="
สำหรับการเข้ารหัส URL ที่ปลอดภัยเช่นเดียวกับbase64.urlsafe_b64encode(...)
ใน Python รหัสด้านล่างใช้งานได้กับฉัน 100%
function base64UrlSafeEncode(string $input)
{
return str_replace(['+', '/'], ['-', '_'], base64_encode($input));
}
ใช่มันปลอดภัยเสมอ แน่นอน base64 ประกอบด้วย:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
แต่เข้ารหัส base64 +
สตริงมักจะไม่มี +
จะถูกแปลงเป็นพื้นที่ว่างส่งผลให้เกิดการถอดรหัสสตริงที่ไม่ถูกต้อง /
ปลอดภัยในคู่รับพารามิเตอร์ =
อยู่เสมอที่ส่วนท้ายของสตริงที่เข้ารหัส base64 และฝั่งเซิร์ฟเวอร์สามารถแก้ไข=
ได้โดยตรง