عندما كنت من المفترض أن استخدام الهروب بدلا من encodeURI / encodeURIComponent?

StackOverflow https://stackoverflow.com/questions/75980

سؤال

عند ترميز سلسلة استعلام ليتم إرسالها إلى ملقم ويب - عندما تستخدمها escape() وعندما تستخدمها encodeURI() أو encodeURIComponent():

استخدام الهروب:

escape("% +&=");

أو

استخدام encodeURI() / encodeURIComponent()

encodeURI("http://www.google.com?var1=value1&var2=value2");

encodeURIComponent("var1=value1&var2=value2");
هل كانت مفيدة؟

المحلول

الهروب()

لا تستخدم ذلك!escape() هو محدد في القسم B. 2.1.2 الهروب و إدخال نص المرفق باء يقول:

...كل من ميزات اللغة والسلوكيات المحددة في هذا المرفق لديك واحد أو أكثر غير مرغوب فيه الخصائص و في غياب إرث من شأنه أن يكون استخدام إزالتها من هذه المواصفات....
...المبرمجين يجب عدم استخدام أو نفترض وجود هذه السمات والسلوكيات عند كتابة جديدة ECMAScript رمز....

السلوك:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

خاصة يتم ترميز الأحرف باستثناء:@*_+-./

الست عشري شكل الشخصيات التي رمز وحدة قيمة 0xFF أو أقل ، رقمين تسلسل الهروب: %xx.

بالنسبة الشخصيات مع أكبر رمز وحدة من أربعة أرقام شكل %uxxxx يتم استخدامه.هذا غير مسموح به ضمن سلسلة الاستعلام (على النحو المحدد في RFC3986):

query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

علامة النسبة المئوية مسموح فقط إذا كان مباشرة تليها اثنين hexdigits, في المئة تليها u لا يسمح.

encodeURI()

استخدام encodeURI عندما كنت ترغب في العمل URL.جعل هذه الدعوة:

encodeURI("http://www.example.org/a file with spaces.html")

للحصول على:

http://www.example.org/a%20file%20with%20spaces.html

لا تتصل encodeURIComponent لأن ذلك من شأنه أن يدمر URL والعودة

http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html

encodeURIComponent()

استخدام encodeURIComponent عندما تريد ترميز قيمة معلمة URL.

var p1 = encodeURIComponent("http://example.org/?a=12&b=55")

ثم يمكنك إنشاء عنوان URL تحتاج:

var url = "http://example.net/?param1=" + p1 + "&param2=99";

وسوف تحصل على هذا URL الكامل:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=99

علما بأن encodeURIComponent لا الهروب ' حرف.مشترك هو علة استخدامه لإنشاء html سمات مثل href='MyUrl', التي يمكن أن تعاني حقنة علة.إذا كنت بناء html من السلاسل ، إما استخدام " بدلا من ' للسمة يقتبس, أو إضافة طبقة إضافية من التشفير (' يمكن ترميز %27).

لمزيد من المعلومات حول هذا النوع من الترميز يمكنك التحقق من: http://en.wikipedia.org/wiki/Percent-encoding

نصائح أخرى

الفرق بين encodeURI() و encodeURIComponent() هي بالضبط 11 الأحرف المشفرة بواسطة encodeURIComponent ولكن ليس قبل encodeURI:

Table with the ten differences between encodeURI and encodeURIComponent

أنا ولدت هذا الجدول بسهولة مع وحدة التحكم.الجدول في جوجل كروم مع هذا الرمز:

var arr = [];
for(var i=0;i<256;i++) {
  var char=String.fromCharCode(i);
  if(encodeURI(char)!==encodeURIComponent(char)) {
    arr.push({
      character:char,
      encodeURI:encodeURI(char),
      encodeURIComponent:encodeURIComponent(char)
    });
  }
}
console.table(arr);

لقد وجدت هذه المادة مفيدة :جافا سكريبت الجنون:سلسلة الاستعلام تحليل

لقد وجدت أنه عندما كنت أحاول أن أفهم لماذا decodeURIComponent لم يفك '+' بشكل صحيح.هنا مقتطف:

String:                         "A + B"
Expected Query String Encoding: "A+%2B+B"
escape("A + B") =               "A%20+%20B"     Wrong!
encodeURI("A + B") =            "A%20+%20B"     Wrong!
encodeURIComponent("A + B") =   "A%20%2B%20B"   Acceptable, but strange

Encoded String:                 "A+%2B+B"
Expected Decoding:              "A + B"
unescape("A+%2B+B") =           "A+++B"       Wrong!
decodeURI("A+%2B+B") =          "A+++B"       Wrong!
decodeURIComponent("A+%2B+B") = "A+++B"       Wrong!

encodeURIComponent لا ترميز -_.!~*'(), تسبب مشكلة في نشر البيانات php في سلسلة xml.

على سبيل المثال:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

العامة الهروب مع encodeURI
%3Cxml%3E%3Ctext%20x=%22100%22%20y=%22150%22%20value=%22It's%20a%20value%20with%20single%20quote%22%20/%3E%20%3C/xml%3E

يمكنك أن ترى, اقتباس مفردة غير المشفرة.لحل المشكلة أنا خلقت وظائف اثنين لحل المسألة في مشروع ترميز URL:

function encodeData(s:String):String{
    return encodeURIComponent(s).replace(/\-/g, "%2D").replace(/\_/g, "%5F").replace(/\./g, "%2E").replace(/\!/g, "%21").replace(/\~/g, "%7E").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
}

من أجل فك URL:

function decodeData(s:String):String{
    try{
        return decodeURIComponent(s.replace(/\%2D/g, "-").replace(/\%5F/g, "_").replace(/\%2E/g, ".").replace(/\%21/g, "!").replace(/\%7E/g, "~").replace(/\%2A/g, "*").replace(/\%27/g, "'").replace(/\%28/g, "(").replace(/\%29/g, ")"));
    }catch (e:Error) {
    }
    return "";
}

encodeURI() - الهروب() وظيفة جافا سكريبت الهروب ، وليس HTTP.

صغيرة جدول مقارنة جافا مقابلجافا سكريبت مقابلPHP.

1. Java URLEncoder.encode (using UTF8 charset)
2. JavaScript encodeURIComponent
3. JavaScript escape
4. PHP urlencode
5. PHP rawurlencode

char   JAVA JavaScript --PHP---
[ ]     +    %20  %20  +    %20
[!]     %21  !    %21  %21  %21
[*]     *    *    *    %2A  %2A
[']     %27  '    %27  %27  %27 
[(]     %28  (    %28  %28  %28
[)]     %29  )    %29  %29  %29
[;]     %3B  %3B  %3B  %3B  %3B
[:]     %3A  %3A  %3A  %3A  %3A
[@]     %40  %40  @    %40  %40
[&]     %26  %26  %26  %26  %26
[=]     %3D  %3D  %3D  %3D  %3D
[+]     %2B  %2B  +    %2B  %2B
[$]     %24  %24  %24  %24  %24
[,]     %2C  %2C  %2C  %2C  %2C
[/]     %2F  %2F  /    %2F  %2F
[?]     %3F  %3F  %3F  %3F  %3F
[#]     %23  %23  %23  %23  %23
[[]     %5B  %5B  %5B  %5B  %5B
[]]     %5D  %5D  %5D  %5D  %5D
----------------------------------------
[~]     %7E  ~    %7E  %7E  ~
[-]     -    -    -    -    -
[_]     _    _    _    _    _
[%]     %25  %25  %25  %25  %25
[\]     %5C  %5C  %5C  %5C  %5C
----------------------------------------
char  -JAVA-  --JavaScript--  -----PHP------
[ä]   %C3%A4  %C3%A4  %E4     %C3%A4  %C3%A4
[ф]   %D1%84  %D1%84  %u0444  %D1%84  %D1%84

أنصح بعدم استخدام واحدة من تلك الطرق كما هو.الكتابة الخاصة بك وظيفة الذي يفعل الشيء الصحيح.

MDN وقد أعطى مثالا جيدا على ترميز url هو مبين أدناه.

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" + encodeRFC5987ValueChars(fileName);

console.log(header); 
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"


function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            //  so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

تذكر أيضا أنهم جميعا ترميز مجموعات مختلفة من الشخصيات ، واختيار واحد التي تحتاج إليها بشكل مناسب.encodeURI() ترميز أحرف أقل من encodeURIComponent () ، الذي يشفر أقل (و أيضا مختلفة ، dannyp نقطة) حرفا من الهروب().

لغرض ترميز جافا سكريبت أعطت ثلاثة يحمل في ثناياه عوامل وظائف -

  1. الهروب() - لا ترميز @*/+ هذا الأسلوب هو مستنكر بعد ECMA 3 لذلك يجب تجنبها.

  2. encodeURI() - لا ترميز ~!@#$&*()=:/,;?+' فإنه يفترض أن URI هو استكمال URI ، لذلك لا ترميز محفوظة الشخصيات التي لها معنى خاص في URI.وتستخدم هذه الطريقة عندما يكون القصد من ذلك هو تحويل URL الكامل بدلا من جزء من URL.على سبيل المثال - encodeURI('http://stackoverflow.com'); سوف تعطي - http://stackoverflow.com

  3. encodeURIComponent() -لا ترميز - _ . ! ~ * ' ( ) هذه الوظيفة يشفر معرف الموارد الموحد (URI) مكون عن طريق استبدال كل مثيل من بعض الشخصيات من جانب واحد, اثنان, ثلاثة, أو أربعة تسلسلات الهروب تمثل UTF-8 ترميز الحرف.هذه الطريقة يجب أن تستخدم لتحويل مكون من URL.فعلى سبيل المثال بعض مدخلات المستخدم يحتاج إلى إلحاق على سبيل المثال - encodeURI('http://stackoverflow.com'); سوف تعطي - http%3A%2F%2Fstackoverflow.com

كل هذا الترميز تتم في UTF 8 أنا.e الشخصيات سيتم تحويلها في UTF-8 الشكل.

encodeURIComponent تختلف من encodeURI في ذلك ترميز محفوظة الشخصيات وعدد علامة # من encodeURI

لقد وجدت أن تجريب أساليب مختلفة هو جيد التعقل تحقق حتى بعد أن مؤشر جيد على الاستخدامات المختلفة والقدرات.

لتحقيق هذه الغاية وجدت هذا الموقع مفيدة للغاية في تأكيد شكوكي أن أفعل شيء مناسب.وقد ثبت أيضا مفيدة فك أحد encodeURIComponent رائد سلسلة التي يمكن أن تكون صعبة بل إلى تفسير.كبير المرجعية إلى:

http://www.the-art-of-web.com/javascript/escape/

مستوحاة من يوهان الجدول, لقد قرر تمديد الجدول.أردت أن أرى أي أحرف ASCII الحصول على ترميز.

screenshot of console.table

var ascii = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

var encoded = [];

ascii.split("").forEach(function (char) {
    var obj = { char };
    if (char != encodeURI(char))
        obj.encodeURI = encodeURI(char);
    if (char != encodeURIComponent(char))
        obj.encodeURIComponent = encodeURIComponent(char);
    if (obj.encodeURI || obj.encodeURIComponent)
        encoded.push(obj);
});

console.table(encoded);

ويبين الجدول فقط ترميز الأحرف.خلايا فارغة يعني أن أصلي و ترميز الأحرف هي نفسها.


فقط أن تكون إضافية, انا إضافة آخر الجدول urlencode() مقابل rawurlencode().الفرق الوحيد يبدو أن ترميز حرف مسافة.

screenshot of console.table

<script>
<?php
$ascii = str_split(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1);
$encoded = [];
foreach ($ascii as $char) {
    $obj = ["char" => $char];
    if ($char != urlencode($char))
        $obj["urlencode"] = urlencode($char);
    if ($char != rawurlencode($char))
        $obj["rawurlencode"] = rawurlencode($char);
    if (isset($obj["rawurlencode"]) || isset($obj["rawurlencode"]))
        $encoded[] = $obj;
}
echo "var encoded = " . json_encode($encoded) . ";";
?>
console.table(encoded);
</script>

لدي وظيفة...

var escapeURIparam = function(url) {
    if (encodeURIComponent) url = encodeURIComponent(url);
    else if (encodeURI) url = encodeURI(url);
    else url = escape(url);
    url = url.replace(/\+/g, '%2B'); // Force the replacement of "+"
    return url;
};

الجواب المقبول هو جيد.تمديد على الجزء الأخير:

علما بأن encodeURIComponent لا الهروب ' حرف.مشترك الخلل هو استخدامه لإنشاء html سمات مثل href='MyUrl' ، يمكن أن تعاني حقنة علة.إذا كنت بناء html من سلاسل إما استخدام "بدلا من' السمة يقتبس, أو إضافة طبقة إضافية من التشفير (' يمكن ترميز %27).

إذا كنت تريد أن تكون على الجانب الآمن ، في المئة ترميز تحفظ الشخصيات يجب أن يكون ترميز كذلك.

يمكنك استخدام هذا الأسلوب إلى الهروب منها (المصدر موزيلا)

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

// fixedEncodeURIComponent("'") --> "%27"

الحديث كتابة @يوهان-echavarria الجواب:

console.log(
    Array(256)
        .fill()
        .map((ignore, i) => String.fromCharCode(i))
        .filter(
            (char) =>
                encodeURI(char) !== encodeURIComponent(char)
                    ? {
                          character: char,
                          encodeURI: encodeURI(char),
                          encodeURIComponent: encodeURIComponent(char)
                      }
                    : false
        )
)

أو إذا كان يمكنك استخدام جدول استبدال console.log مع console.table (على أجمل الإخراج).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top