เข้ารหัส URL ใน JavaScript หรือไม่


2469

คุณเข้ารหัส URL อย่างปลอดภัยโดยใช้ JavaScript เพื่อให้สามารถใส่ลงในสตริง GET ได้อย่างไร

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;

ฉันคิดว่าคุณต้องเข้ารหัสmyUrlตัวแปรในบรรทัดที่สองหรือไม่


22
ลองมองเข้าไปในencodeURI ()และdecodeURI ()
Zack The Human

ดูฟังก์ชั่น urlencode JavaScript
Yanni

1
คุณสามารถใช้เครื่องมือนี้ได้ที่นี่: phillihp.com/toolz/url-encode-decode
phillihp

2
encodeURIComponent ()
Andrew

คำตอบ:


2791

ตรวจสอบในตัวฟังก์ชั่นencodeURIComponent (STR)และencodeURI (STR)
ในกรณีของคุณสิ่งนี้ควรใช้งานได้:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

12
วิธีการเกี่ยวกับการเพิ่มคำอธิบาย @cms ให้? escapeเป็นตัวเลือกที่ถูกต้อง
hitautodestruct

11
ตาม @CMS encodeURIไม่ปลอดภัยสำหรับการเข้ารหัส URL
Ifnot

13
@AnaelFavre เพราะมันจะหมายถึงการเข้ารหัส URL ทั้งหมดซึ่งไม่อนุญาตให้มีตัวอักษรเช่น:, /, @ฯลฯ เหล่านี้ 2 วิธีไม่ได้ที่จะใช้แทนกันได้คุณต้องรู้ว่าสิ่งที่คุณกำลังเข้ารหัสจะใช้วิธีการที่เหมาะสม
Buu Nguyen


ตามที่ระบุไว้ในคำตอบในหน้านี้อีก , เว็บไซต์นี้อย่างรายละเอียดเหตุผลที่จะใช้วิธีการนี้
แบรดสวนสาธารณะ

1520

คุณมีสามตัวเลือก:

  • escape() จะไม่เข้ารหัส: @*/+

  • encodeURI() จะไม่เข้ารหัส: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() จะไม่เข้ารหัส: ~!*()'

แต่ในกรณีของคุณหากคุณต้องการส่งURLไปยังGETพารามิเตอร์ของหน้าอื่นคุณควรใช้escapeหรือencodeURIComponentไม่encodeURIใช้

ดูที่คำถามแบบสแต็คโอเวอร์โฟลว์แนวปฏิบัติที่ดีที่สุด: หลบหนีหรือเข้ารหัส / encodeURIC ส่วนประกอบสำหรับการอภิปรายเพิ่มเติม


76
การเข้ารหัสอักขระที่ใช้กับการหลบหนีเป็นตัวแปร ติดกับ encodeURI และ encodeURIComponent ซึ่งใช้ UTF-8
erickson

6
ระวัง. การหลบหนีที่แปลงอักขระที่ไม่ใช่ ASCII เข้า Unicode %uxxxลำดับหนีของมันเช่น
opteronn

4
ฉันกำลังใช้ encodeURIC และสังเกตว่ามันจะไม่เข้ารหัสอักขระไปป์ |
kevzettler

15
@ kevzettler - ทำไมต้องทำเช่นนั้น? ท่อไม่ได้มีความสำคัญทางความหมายใน URI
nickf

4
@GiovanniP: ผู้ที่อนุญาตให้ใช้อักขระเยอรมันฝรั่งเศสญี่ปุ่นจีนอาราบิกเป็นอินพุตและส่งพารามิเตอร์เหล่านี้ผ่าน GET หรือ POST
Tseng

180

encodeURIComponent()ติดกับ ฟังก์ชันencodeURI()ไม่รบกวนการเข้ารหัสอักขระจำนวนมากที่มีความสำคัญเชิงความหมายใน URL (เช่น "#", "?" และ "&") escape()เลิกใช้แล้วและไม่สนใจที่จะเข้ารหัสอักขระ "+" ซึ่งจะถูกตีความว่าเป็นช่องว่างที่เข้ารหัสบนเซิร์ฟเวอร์ (และตามที่คนอื่น ๆ ที่นี่ชี้ให้เห็นว่าการเข้ารหัส URL ไม่ใช่อักขระ ASCII ที่ไม่ถูกต้อง)

มีคำอธิบายที่encodeURI()encodeURIComponent()ดีเกี่ยวกับความแตกต่างระหว่างและที่อื่น ๆ หากคุณต้องการที่จะเข้ารหัสบางสิ่งบางอย่างเพื่อที่จะสามารถได้อย่างปลอดภัยถูกรวมเป็นส่วนหนึ่งของ URI ที่ (เช่นเป็นพารามิเตอร์สตริงแบบสอบถาม), encodeURIComponent()คุณต้องการที่จะใช้


83

คำตอบที่ดีที่สุดคือการใช้encodeURIComponentกับค่าในสตริงการสืบค้น (และไม่มีที่อื่น)

อย่างไรก็ตามฉันพบว่า API จำนวนมากต้องการแทนที่ "" ด้วย "+" ดังนั้นฉันจึงต้องใช้สิ่งต่อไปนี้:

const value = encodeURIComponent(value).replace('%20','+');
const url = 'http://example.com?lang=en&key=' + value

escapeมีการใช้งานแตกต่างกันในเบราว์เซอร์ที่แตกต่างกันและencodeURIไม่ได้เข้ารหัสอักขระจำนวนมาก (เช่น # และแม้กระทั่ง /) - มันถูกสร้างขึ้นเพื่อใช้กับ URI / URL แบบเต็มโดยไม่ทำให้แตก - ซึ่งไม่มีประโยชน์หรือปลอดภัยอย่างยิ่ง

และเป็น @Jochem ชี้ให้เห็นด้านล่างนี้คุณอาจต้องการใช้encodeURIComponent()บน (แต่ละคน) ชื่อโฟลเดอร์ แต่ด้วยเหตุผลใด API เหล่านี้ดูเหมือนจะไม่ต้องการ+ในชื่อโฟลเดอร์เพื่อให้ธรรมดาเก่าencodeURIComponentผลงานที่ดี

ตัวอย่าง:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;

22
โปรดทราบว่าคุณควรแทนที่% 20 ด้วยสัญลักษณ์ + หลังเครื่องหมายคำถามแรก (ซึ่งเป็นส่วน 'แบบสอบถาม' ของ URL) http://somedomain/this dir has spaces/info.php?a=this has also spacesสมมติว่าผมต้องการที่จะเรียกดู ควรแปลงเป็น: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacesแต่การใช้งานจำนวนมากอนุญาตให้ '% 20' ในการสอบถามถูกแทนที่ด้วย '+' อย่างไรก็ตามคุณไม่สามารถแทนที่ '% 20' ด้วย '+' ในส่วนพา ธ ของ URL ซึ่งจะส่งผลให้เกิดข้อผิดพลาดไม่พบเว้นแต่คุณจะมีไดเรกทอรีที่มี+ช่องว่างแทน
Jochem Kuijpers

@Jochem Kuijpers แน่นอนคุณจะไม่ใส่ "+" ในไดเรกทอรี ฉันจะใช้สิ่งนี้กับค่าพารามิเตอร์การสืบค้นเท่านั้น (หรือคีย์หากจำเป็น) ไม่ใช่ URL ทั้งหมดหรือแม้กระทั่งสตริงข้อความค้นหาทั้งหมด
Ryan Taylor

ฉันจะแทนที่ค่าแทนที่จะเป็นผลลัพธ์ของการเข้ารหัส
njzk2

1
@ njzk2 น่าเสียดายที่encodeURIComponent('+')จะให้คุณ%2Bดังนั้นคุณต้องใช้สองนิพจน์ปกติ ... ซึ่งฉันคิดว่าเป็นสาเหตุที่ทำให้งานนี้เพราะ '+' เป็น '' ถูกเข้ารหัสแตกต่างกันในตอนท้าย
Ryan Taylor

ไม่มีเหตุผลที่จะแปล% 20 เป็น "+" ลำดับ escape ที่ถูกต้องสำหรับพื้นที่ ASCII คือ% 20 ไม่ใช่ "+" ซึ่งไม่ได้กล่าวถึงใน RFC 3986 ( tools.ietf.org/html/rfc3986 ) "+" ถูกใช้ในปี 1990; มันล้าสมัยแล้วและได้รับการสนับสนุนด้วยเหตุผลดั้งเดิมเท่านั้น อย่าใช้มัน
xhienne

40

หากคุณกำลังใช้ jQuery ฉันจะไปหา$.paramวิธี URL นั้นเข้ารหัสฟิลด์การแมปวัตถุให้เป็นค่าซึ่งง่ายต่อการอ่านมากกว่าการเรียกเมธอด escape ในแต่ละค่า

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1

ฉันคิดว่าตัวอย่างที่ให้ไว้เพียงพอแล้ว หากคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับ $ .param บนapi.jquery.com/jquery.param
Maksym Kozlenko

เกือบทุกคนใช้ jQuery และฉันรู้สึกสะดวกสบายมากขึ้นด้วยสิ่งนี้แทนที่จะเป็น encoreURIComponent
Cyril Duchon-Doris

12

encodeURIComponent () เป็นวิธีที่จะไป

var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

แต่คุณควรจำไว้ว่ามีความแตกต่างเล็กน้อยจากรุ่น php urlencode()และตามที่ @CMS กล่าวถึงมันจะไม่เข้ารหัสถ่านทุกตัว พวกที่http://phpjs.org/functions/urlencode/ทำให้ js เทียบเท่ากับphpencode():

function urlencode(str) {
  str = (str + '').toString();

  // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
  // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
  return encodeURIComponent(str)
    .replace('!', '%21')
    .replace('\'', '%27')
    .replace('(', '%28')
    .replace(')', '%29')
    .replace('*', '%2A')
    .replace('%20', '+');
}

10

หากต้องการเข้ารหัส URL ดังที่ได้กล่าวไว้ก่อนหน้านี้คุณมีสองฟังก์ชัน:

encodeURI()

และ

encodeURIComponent()

เหตุผลที่มีอยู่ทั้งคู่คือเหตุผลแรกที่รักษา URL ไว้โดยมีความเสี่ยงที่จะไม่ปล่อยสิ่งต่าง ๆ มากเกินไปในขณะที่สิ่งที่สองเข้ารหัสทุกสิ่งที่ต้องการ

ด้วยครั้งแรกคุณสามารถคัดลอก URL ที่หลบหนีใหม่ไปยังแถบที่อยู่ (ตัวอย่าง) และมันจะทำงาน อย่างไรก็ตาม '& # 39; s unescaped ของคุณจะรบกวนตัวคั่นฟิลด์,' = 'จะรบกวนชื่อและค่าของฟิลด์และ' + 'จะมีลักษณะช่องว่าง แต่สำหรับข้อมูลง่ายๆเมื่อคุณต้องการรักษาลักษณะ URL ของสิ่งที่คุณกำลังหลบหนีอยู่

อย่างที่สองคือทุกสิ่งที่คุณต้องทำเพื่อให้แน่ใจว่าไม่มีสิ่งใดในสตริงของคุณรบกวนกับ URL มันทำให้ตัวละครที่ไม่สำคัญแตกต่างกันซึ่งไม่ได้มีการ Escape เพื่อให้ URL ยังคงเป็นมนุษย์ที่สามารถอ่านได้โดยไม่รบกวน URL ที่เข้ารหัสด้วยวิธีนี้จะไม่ทำงานเป็น URL อีกต่อไปโดยไม่ยกเลิกการลบทิ้ง

ดังนั้นหากคุณสามารถใช้เวลาคุณต้องการใช้ encodeURIComponent () - ก่อนเพิ่มคู่ชื่อ / ค่าเข้ารหัสทั้งชื่อและค่าโดยใช้ฟังก์ชันนี้ก่อนที่จะเพิ่มลงในสตริงแบบสอบถาม

ฉันมีเวลาที่ยากลำบากในการหาเหตุผลในการใช้ encodeURI () - ฉันจะปล่อยให้คนฉลาดกว่านี้


5

สิ่งที่คล้ายกันฉันลองกับจาวาสคริปต์ปกติ

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}

5

วิธีที่สง่างาม

ในความเห็นที่ต่ำต้อยของฉันวิธีที่ยอดเยี่ยมที่สุดในการเข้ารหัสพารามิเตอร์แบบสอบถามคือการสร้างวัตถุที่มีพารามิเตอร์เช่น

const queryParams = { param1: 'value1', param2: 'value2' }

แล้วเข้ารหัสโดยใช้:

const queryString = new URLSearchParams(queryParams).toString()

ตามที่ระบุไว้ในคำตอบนี้: https://stackoverflow.com/a/53171438/7284582


4

เพื่อป้องกันการเข้ารหัสสองครั้งเป็นความคิดที่ดีที่จะถอดรหัส URL ก่อนการเข้ารหัส (หากคุณกำลังจัดการกับผู้ใช้ที่ป้อน URL ตัวอย่างเช่นซึ่งอาจถูกเข้ารหัสไว้แล้ว)

ให้บอกว่าเรามีabc%20xyz 123เป็นอินพุต (หนึ่งช่องว่างถูกเข้ารหัสแล้ว):

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"

4

การเข้ารหัส URL คืออะไร:

ควรเข้ารหัส URL เมื่อมีอักขระพิเศษอยู่ใน URL ตัวอย่างเช่น:

console.log(encodeURIComponent('?notEncoded=&+'));

เราสามารถสังเกตได้ในตัวอย่างนี้ว่าตัวละครทั้งหมดยกเว้นสตริงnotEncodedจะถูกเข้ารหัสด้วยเครื่องหมาย% การเข้ารหัส URL ยังเป็นที่รู้จักกันในนามการเข้ารหัสแบบเปอร์เซ็นต์เพราะมันจะหนีอักขระพิเศษทั้งหมดด้วย% หลังจากนี้% เซ็นชื่อตัวละครทุกตัวมีรหัสที่ไม่ซ้ำ

ทำไมเราต้องเข้ารหัส URL:

อักขระบางตัวมีค่าพิเศษในสตริง URL ตัวอย่างเช่น ตัวอักษรหมายถึงจุดเริ่มต้นของสตริงแบบสอบถาม เพื่อค้นหาแหล่งข้อมูลบนเว็บอย่างประสบความสำเร็จจึงจำเป็นที่จะต้องแยกแยะระหว่างเมื่อตัวละครมีความหมายว่าเป็นส่วนหนึ่งของสตริงหรือส่วนหนึ่งของโครงสร้าง URL

เราจะทำการเข้ารหัส URL ใน JS ได้อย่างไร:

JS เสนอพวงของการสร้างในฟังก์ชั่นยูทิลิตี้ที่เราสามารถใช้ในการเข้ารหัส URL ได้อย่างง่ายดาย นี่เป็นสองทางเลือกที่สะดวกสบาย:

  1. encodeURIComponent(): ใช้องค์ประกอบของ URI เป็นอาร์กิวเมนต์และส่งคืนสตริง URI ที่เข้ารหัส
  2. encodeURI(): ใช้ URI เป็นอาร์กิวเมนต์และส่งคืนสตริง URI ที่เข้ารหัส

ตัวอย่างและคำเตือน:

ได้ตระหนักถึงการไม่ผ่านใน URL ทั้งหมด (รวมทั้งรูปแบบเช่น https: //) encodeURIComponent()ลง สิ่งนี้สามารถแปลงให้เป็น URL ที่ใช้งานไม่ได้ ตัวอย่างเช่น:

// for a whole URI don't use encodeURIComponent it will transform
// the / characters and the URL won't fucntion properly
console.log(encodeURIComponent("http://www.random.com/specials&char.html"));

// instead use encodeURI for whole URL's
console.log(encodeURI("http://www.random.com/specials&char.html"));

เราสามารถสังเกตได้ว่าเราใส่ URL ทั้งหมดไว้ในencodeURIComponentที่ที่เครื่องหมายสแลช (/) ถูกแปลงเป็นอักขระพิเศษ สิ่งนี้จะทำให้ URL ทำงานไม่ถูกต้องอีกต่อไป

ดังนั้น (ตามชื่อหมายถึง) ใช้:

  1. encodeURIComponent ในบางส่วนของ URL ที่คุณต้องการเข้ารหัส
  2. encodeURI ใน URL ทั้งหมดที่คุณต้องการเข้ารหัส

3

ไม่มีอะไรทำงานให้ฉัน ทั้งหมดที่ฉันเห็นคือ HTML ของหน้าเข้าสู่ระบบกลับมาที่ฝั่งไคลเอ็นต์ด้วยรหัส 200 (302 ตอนแรก แต่คำขอ Ajax เดียวกันกำลังโหลดหน้าเข้าสู่ระบบภายในคำขอ Ajax อื่นซึ่งควรจะเปลี่ยนเส้นทางแทนที่จะโหลดแบบธรรมดา ข้อความของหน้าเข้าสู่ระบบ)

ในตัวควบคุมการเข้าสู่ระบบฉันเพิ่มบรรทัดนี้:

Response.Headers["land"] = "login";

และในตัวจัดการ Ajax ทั่วโลกฉันทำสิ่งนี้:

$(function () {
    var $document = $(document);
    $document.ajaxSuccess(function (e, response, request) {
        var land = response.getResponseHeader('land');
        var redrUrl = '/login?ReturnUrl=' + encodeURIComponent(window.location);
        if(land) {
            if (land.toString() === 'login') {
                window.location = redrUrl;
            }
        }
    });
});

ตอนนี้ฉันไม่มีปัญหาใด ๆ และใช้งานได้อย่างมีเสน่ห์


2

เข้ารหัสสตริง URL

    var url = $ ( ตำแหน่ง) attr ( 'href' ); // รับ url ปัจจุบัน// OR var url = 'โฟลเดอร์ / index.html? param = # 23dd & noob = ใช่' ; // หรือระบุอย่างใดอย่างหนึ่ง 
    
      

var encodedUrl = encodeURIComponent(url); console.log(encodedUrl); //outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes for more info go http://www.sitepoint.com/jquery-decode-url-string

2

นี่คือการสาธิตสดของencodeURIComponent()และdecodeURIComponent()JS ในตัวฟังก์ชั่น:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>

1

คุณสามารถใช้ห้องสมุด esapi และเข้ารหัส URL ของคุณโดยใช้ฟังก์ชั่นด้านล่าง ฟังก์ชันทำให้มั่นใจได้ว่า '/' จะไม่สูญหายไปกับการเข้ารหัสในขณะที่ส่วนที่เหลือของเนื้อหาข้อความถูกเข้ารหัส:

function encodeUrl(url)
{
    String arr[] = url.split("/");
    String encodedUrl = "";
    for(int i = 0; i<arr.length; i++)
    {
        encodedUrl = encodedUrl + ESAPI.encoder().encodeForHTML(ESAPI.encoder().encodeForURL(arr[i]));
        if(i<arr.length-1) encodedUrl = encodedUrl + "/";
    }
    return url;
}

https://www.owasp.org/index.php/ESAPI_JavaScript_Readme


1

ใช้ fixedEncodeURIComponentฟังก์ชั่นเพื่อให้สอดคล้องกับRFC 3986อย่างเคร่งครัด:

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

1

คุณไม่ควรใช้encodeURIComponent()โดยตรง

ดูที่ RFC3986: Uniform Resource Identifier (URI): ไวยากรณ์ทั่วไป

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "," / ";" / "="

วัตถุประสงค์ของตัวละครที่สงวนไว้คือการให้ชุดของตัวละครที่คั่นที่แตกต่างจากข้อมูลอื่น ๆ ภายใน URI

เหล่าตัวละครจากที่สงวนคำนิยาม URI ใน RFC3986 encodeURIComponent()กำลังไม่หนี

MDN Web Docs: encodeURIComponent ()

หากต้องการเข้มงวดมากขึ้นในการปฏิบัติตาม RFC 3986 (ซึ่งสงวน!, ', (,) และ *) แม้ว่าตัวละครเหล่านี้ไม่มีการใช้ URI อย่างเป็นทางการ แต่ก็สามารถใช้ต่อไปนี้ได้อย่างปลอดภัย:

ใช้ฟังก์ชั่น MDN Web Docs ...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.