การเข้ารหัส HTML สูญหายเมื่อแอตทริบิวต์อ่านจากช่องป้อนข้อมูล


745

ฉันใช้จาวาสคริปต์เพื่อดึงค่าออกมาจากเขตข้อมูลที่ซ่อนอยู่และแสดงในกล่องข้อความ ค่าในเขตข้อมูลที่ซ่อนอยู่ถูกเข้ารหัส

ตัวอย่างเช่น,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

ถูกดึงเข้าไป

<input type='text' value='chalk &amp; cheese' />

ผ่าน jQuery เพื่อรับค่าจากฟิลด์ที่ซ่อนอยู่ (ตอนนี้ฉันเสียการเข้ารหัส):

$('#hiddenId').attr('value')

ปัญหาคือเมื่อฉันอ่านchalk &amp; cheeseจากเขตข้อมูลที่ซ่อนอยู่ JavaScript ดูเหมือนจะสูญเสียการเข้ารหัส chalk & cheeseฉันไม่ต้องการความคุ้มค่าที่จะ ฉันต้องการที่แท้จริงamp;จะต้องเก็บไว้

มีห้องสมุด JavaScript หรือวิธี jQuery ที่ HTML จะเข้ารหัสสตริงหรือไม่


คุณสามารถแสดง Javascript ที่คุณใช้อยู่ได้หรือไม่?
Sinan Taifour

1
ได้เพิ่มวิธีที่ฉันได้รับความคุ้มค่าจากสนามที่ซ่อนอยู่
AJM

5
อย่าใช้วิธีการ innerHTML (วิธี jQuery .html () ใช้ InnerHTML) เช่นเดียวกับเบราว์เซอร์ (ฉันเพิ่งทดสอบ Chrome) เบราว์เซอร์บางตัวสิ่งนี้จะไม่หลีกเลี่ยงคำพูดดังนั้นถ้าคุณใส่ค่าลงในค่าคุณลักษณะ คุณจะพบกับช่องโหว่ XSS
James Roper

21
ในบริบทใดchalkและcheeseเคยใช้ร่วมกัน 0_o
d -_- b

2
@d -_- b เมื่อเปรียบเทียบสองรายการ ตัวอย่าง. พวกเขาแตกต่างกันเหมือนชอล์คและชีส;)
Anurag

คำตอบ:


1067

แก้ไข:คำตอบนี้โพสต์เมื่อนานมาแล้วและhtmlDecodeฟังก์ชั่นแนะนำช่องโหว่ XSS มันได้รับการแก้ไขเปลี่ยนองค์ประกอบชั่วคราวจาก a divเป็นtextareaโอกาสในการลด XSS แต่ปัจจุบันผมจะขอแนะนำให้คุณใช้ DOMParser API ที่แนะนำในanwswer อื่น ๆ


ฉันใช้ฟังก์ชั่นเหล่านี้:

function htmlEncode(value){
  // Create a in-memory element, set its inner text (which is automatically encoded)
  // Then grab the encoded contents back out. The element never exists on the DOM.
  return $('<textarea/>').text(value).html();
}

function htmlDecode(value){
  return $('<textarea/>').html(value).text();
}

โดยทั่วไปองค์ประกอบ textarea จะถูกสร้างขึ้นในหน่วยความจำ แต่จะไม่ผนวกเข้ากับเอกสาร

ในhtmlEncodeฟังก์ชั่นฉันตั้งค่าinnerTextขององค์ประกอบและดึงการเข้ารหัสinnerHTML; ในhtmlDecodeฟังก์ชั่นที่ฉันตั้งinnerHTMLค่าขององค์ประกอบและinnerTextดึง

ตรวจสอบตัวอย่างที่ทำงานที่นี่


95
สิ่งนี้ใช้ได้กับสถานการณ์ส่วนใหญ่ แต่การนำ htmlDecode นี้ไปใช้จะช่วยขจัดช่องว่างพิเศษใด ๆ ดังนั้นสำหรับค่าบางส่วนของ "อินพุต" ให้ป้อน! = htmlDecode (htmlEncode (อินพุต)) นี่เป็นปัญหาสำหรับเราในบางสถานการณ์ ตัวอย่างเช่นหากอินพุต = "<p> \ t สวัสดี \ n มี </p>" การเข้ารหัส / ถอดรหัสแบบไปกลับจะให้ผล "<p> สวัสดีที่นั่น </p>" ส่วนใหญ่เวลานี้ก็โอเค แต่บางครั้งก็ไม่เป็นเช่นนั้น :)
จิ๊บจ๊อป

7
ขอบคุณสำหรับการแก้ปัญหา! ฉันแก้ไขปัญหาการกำจัดช่องว่างพิเศษด้วยการแทนที่บรรทัดใหม่ด้วยเช่น %% NL %% ในค่าข้อความจากนั้นเรียกว่า. html () เพื่อรับค่าที่เข้ารหัส HTML จากนั้นแทนที่ %% NL %% ด้วย <br /> ' s ... ไม่ใช่ bullet bullet แต่ใช้งานได้และผู้ใช้ของฉันไม่น่าจะพิมพ์ %% NL %%
benno

1
สิ่งที่ตลกคือ CSS มีwhite-spaceคุณสมบัติซึ่งแนะนำว่าควรประมวลผลช่องว่างในเนื้อหา HTML อย่างไร ความสำคัญของความหมายก็คือว่า "นี่คือ preformatted ช่องว่างและเส้นแบ่งควรได้รับการเก็บรักษาไว้" สิ่งนี้จะแยกการแยกสไตล์และเนื้อหาออกเพราะถ้าคุณพยายามจัดรูปแบบ HTML ให้เป็น "สวย" หรือคุณปัดไปเรื่อย ๆ ผ่านวงจรการเข้ารหัส / ถอดรหัสแบบนี้การวิ่งของช่องว่าง / ตัวแบ่งจะลดลงและตัวเข้ารหัสไม่มี วิธีการที่จะรู้ว่ามันเป็นการตกลงที่จะทำเช่นนั้นเพราะมันไม่ได้ตระหนักถึงwhite-space:pre-*;ตัวบ่งชี้ในไฟล์ CSS ภายนอก!
Triynko

2
โซลูชันนี้อาจขึ้นอยู่กับว่าหน้านั้นเขียนเป็น html หรือ xhtml ดังนั้นฉันจะชอบโซลูชันที่ไม่เกี่ยวข้องกับ DOM
Phil H

30
แม้ว่าจะได้รับคำตอบในอีกสองปีต่อมาคำตอบจาก @Anentropic ด้านล่างนั้นดีกว่าในทุกด้าน
ชาด

559

เคล็ดลับ jQuery ไม่ได้เข้ารหัสเครื่องหมายคำพูดและใน IE มันจะตัดช่องว่างของคุณ

จากการหลบหนี templatetag ใน Django ซึ่งฉันคิดว่ามีการใช้ / ทดสอบอย่างหนักแล้วฉันได้สร้างฟังก์ชั่นนี้ซึ่งทำสิ่งที่ต้องการ

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

function htmlEscape(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

อัปเดต 2013-06-17:
ในการค้นหาการหลบหนีที่เร็วที่สุดฉันได้พบการใช้replaceAllวิธีนี้:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(อ้างอิงที่นี่: เร็วที่สุด วิธีการเพื่อแทนที่อินสแตนซ์ทั้งหมดของอักขระในสตริง )
ผลลัพธ์ประสิทธิภาพบางอย่างที่นี่:
http://jsperf.com/htmlencoderegex/25

มันให้สตริงผลลัพธ์ที่เหมือนกันกับreplaceโซ่บิวด์อินด้านบน ฉันมีความสุขมากถ้ามีคนอธิบายได้ว่าทำไมมันเร็วขึ้น!

อัปเดต 2015-03-04:
ฉันเพิ่งสังเกตเห็นว่า AngularJS ใช้วิธีการด้านบนทั้งหมด:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

พวกเขาเพิ่มการปรับแต่งสองสามครั้ง - ดูเหมือนว่าพวกเขากำลังจัดการกับปัญหา Unicode ที่คลุมเครือเช่นเดียวกับการแปลงอักขระที่ไม่ใช่ตัวอักษรและตัวเลขทั้งหมดเป็นเอนทิตี ฉันอยู่ภายใต้การแสดงผลหลังไม่จำเป็นตราบใดที่คุณมีชุดอักขระ UTF8 ที่ระบุไว้สำหรับเอกสารของคุณ

ฉันจะทราบว่า (4 ปีต่อมา) Django ยังไม่ได้ทำสิ่งเหล่านี้อย่างใดอย่างหนึ่งดังนั้นฉันไม่แน่ใจว่าพวกเขามีความสำคัญ:
https://github.com/django/django/django/blob/1.8b1/django/utils /html.py#L44

อัพเดท 2016/04/06:คุณอาจต้องการที่จะหลบหนีไปข้างหน้าเฉือน
/ไม่จำเป็นสำหรับการเข้ารหัส HTML ที่ถูกต้องอย่างไรก็ตามOWASP แนะนำให้ใช้เป็นมาตรการความปลอดภัย anti-XSS (ขอบคุณ @JNF สำหรับการแนะนำสิ่งนี้ในความคิดเห็น)

        .replace(/\//g, '&#x2F;');

3
คุณสามารถใช้&apos;แทน&#39;
Ferruccio

32
@Ferruccio ... และด้วยเหตุผลว่าทำไมไม่ใช้ & apos; โปรดดูที่: stackoverflow.com/questions/2083754/... blogs.msdn.com/b/kirillosenkov/archive/2010/03/19/... fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
Anentropic

5
ขอบคุณฉันไม่เคยรู้เลยว่า&apos;ไม่ใช่เอนทิตี HTML ที่ถูกต้อง
Ferruccio

10
โดยไม่ต้อง/g, .replace()เพียงจะเข้ามาแทนที่การแข่งขันครั้งแรก
ThinkingStiff

1
@ Tracker1 ฉันไม่เห็นด้วยถ้าฟังก์ชั่นได้รับการป้อนข้อมูลที่ไม่ถูกต้องมันควรจะเกิดข้อผิดพลาด หากในกรณีการใช้งานเฉพาะที่คุณต้องการจัดการกับอินพุตที่ไม่ถูกต้องในวิธีนั้นให้ตรวจสอบค่าก่อนที่จะเรียกใช้ฟังก์ชันหรือตัดการเรียกฟังก์ชันในการลอง / จับ
Anentropic

80

นี่คือรุ่นที่ไม่ใช่ jQuery ที่เร็วกว่าทั้ง.html()รุ่นjQuery และ.replace()รุ่น สิ่งนี้จะรักษาพื้นที่สีขาวทั้งหมด แต่เหมือนกับ jQuery เวอร์ชันไม่ได้จัดการราคา

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

ความเร็ว: http://jsperf.com/htmlencoderegex/17

ทดสอบความเร็ว

การสาธิต: jsFiddle

เอาท์พุท:

เอาท์พุต

สคริปต์:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>

17
นี่เป็นคำถาม: ทำไมมันไม่ได้เป็นฟังก์ชั่นทั่วโลกใน JS แล้ว!
SEoF

2
รุ่นที่ไม่ใช่ regex ที่.replace()แนะนำโดย @SEoF กลายเป็นเร็วกว่าอย่างมาก: jsperf.com/htmlencoderegex/22
Anentropic

@Anentropic ที่ให้แสงสว่างอย่างรวดเร็ว แต่ฉันไม่คิดว่ามันจะทำงานได้ โดยไม่ต้อง/g, .replace()เป็นเพียงการทำนัดแรก
ThinkingStiff

น่าสนใจใน Firefox ที่คุณสามารถทำได้replace('a', 'b', 'g')ซึ่งทำงานเหมือนกับreplace(/a/g, 'b')... ความเร็วเหมือนกันทุกครั้ง
Anentropic

1
ฉันไม่ได้ :) ฉันเริ่มต้นเพียงแค่ต้องการที่จะจัดการเครื่องหมายคำพูดและฉันได้ลงเอยด้วยการแสวงหาความเร็ว ...
Anentropic

32

ฉันรู้ว่านี่เป็นรุ่นเก่า แต่ฉันต้องการโพสต์รูปแบบของคำตอบที่ยอมรับซึ่งจะทำงานใน IE โดยไม่ต้องลบบรรทัด:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
} 


12

คำตอบที่ดี. โปรดทราบว่าหากค่าในการเข้ารหัสเป็นundefinedหรือnullกับ jQuery 1.4.2 คุณอาจได้รับข้อผิดพลาดเช่น:

jQuery("<div/>").text(value).html is not a function

หรือ

Uncaught TypeError: Object has no method 'html'

ทางออกคือการปรับเปลี่ยนฟังก์ชั่นเพื่อตรวจสอบค่าจริง:

function htmlEncode(value){ 
    if (value) {
        return jQuery('<div/>').text(value).html(); 
    } else {
        return '';
    }
}

8
jQuery('<div/>').text(value || '').html()
roufamatic

3
@roufamatic - ดีหนึ่งซับ แต่การตรวจสอบค่าที่ไม่ว่างเปล่าvalueด้วยเครื่องมือifบันทึกที่จำเป็นต้องสร้าง DIV ในทันทีและคว้ามันคุ้มค่า นี่อาจเป็นสิ่งที่มีประสิทธิภาพมากกว่าถ้าhtmlEncodeถูกเรียกว่าเป็นจำนวนมากและถ้าเป็นไปได้ว่ามันvalueจะว่างเปล่า
leepowers

สวัสดีคุณไม่ได้ & beta เป็นเบต้ารู้หรือไม่ว่าเพราะอะไร
Dilip Rajkumar

11

สำหรับผู้ที่ชอบจาวาสคริปต์ธรรมดานี่คือวิธีที่ฉันใช้อย่างประสบความสำเร็จ:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

6

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

ฉันอาจใช้ความหมายอย่างเคร่งครัดที่นี่ แต่ฉันต้องการให้คุณเข้าใจวัตถุประสงค์ของการเข้ารหัส คำว่า "หลงทาง" ทำให้ดูเหมือนว่าบางสิ่งไม่ทำงานอย่างที่ควรจะเป็น


6

เร็วขึ้นโดยไม่มี jquery คุณสามารถเข้ารหัสอักขระทุกตัวในสตริงของคุณ:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

หรือเพียงกำหนดเป้าหมายตัวละครหลักเพื่อกังวลเกี่ยวกับ (&, inebreaks, <,>, "และ ') เช่น:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>


5

Prototypeมีคลาส String ในตัว ดังนั้นถ้าคุณใช้ / วางแผนที่จะใช้ Prototype มันจะทำสิ่งที่ชอบ:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"

9
หลังจากดูวิธีแก้ปัญหาของ Prototype ทุกอย่างมันก็ทำได้ ... .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); ง่ายพอ
Steve Wortham

5
มันควรทำอะไรที่มีเครื่องหมายคำพูดด้วยหรือไม่ ไม่ดีเลย
Anentropic

@ Anentropic ฉันไม่เห็นว่าทำไมมันต้องทำอะไรกับคำพูด; เนื่องจากไม่จำเป็นต้องใช้เครื่องหมายคำพูดยกเว้นจะอยู่ในค่าแอตทริบิวต์
Andy

ตกลงหลังจากใคร่ครวญฉันใช้ความคิดเห็นนั้นกลับมา - ถ้าคุณสร้าง HTML ขึ้นมาคุณต้องการเข้ารหัสแต่ละส่วนของมันรวมถึงค่าคุณลักษณะดังนั้นฉันเห็นด้วยกับ Anentropic และฉันไม่คิดว่าฟังก์ชั่น Prototypejs นั้นเพียงพอ กรณีนั้น
Andy

4

นี่เป็นวิธีแก้ปัญหาง่ายๆของจาวาสคริปต์ มันขยายวัตถุ String ด้วยวิธีการ "HTMLEncode" ซึ่งสามารถใช้กับวัตถุโดยไม่มีพารามิเตอร์หรือพารามิเตอร์

String.prototype.HTMLEncode = function(str) {
  var result = "";
  var str = (arguments.length===1) ? str : this;
  for(var i=0; i<str.length; i++) {
     var chrcode = str.charCodeAt(i);
     result+=(chrcode>128) ? "&#"+chrcode+";" : str.substr(i,1)
   }
   return result;
}
// TEST
console.log("stetaewteaw æø".HTMLEncode());
console.log("stetaewteaw æø".HTMLEncode("æåøåæå"))

ฉันได้ทำสรุปสาระสำคัญ "วิธีการ HTMLEncode สำหรับจาวาสคริปต์"


3

ขึ้นอยู่กับการฆ่าเชื้อของเชิงมุม ... (ไวยากรณ์โมดูล es6)

// ref: https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js
const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
const NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;

const decodeElem = document.createElement('pre');


/**
 * Decodes html encoded text, so that the actual string may
 * be used.
 * @param value
 * @returns {string} decoded text
 */
export function decode(value) {
  if (!value) return '';
  decodeElem.innerHTML = value.replace(/</g, '&lt;');
  return decodeElem.textContent;
}


/**
 * Encodes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} encoded text
 */
export function encode(value) {
  if (value === null || value === undefined) return '';
  return String(value).
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, value => {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, value => {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}

export default {encode,decode};

ในขณะที่ฉันชอบคำตอบนี้จริง ๆ แล้วฉันคิดว่าเป็นวิธีที่ดีที่ฉันมีข้อสงสัยตัวดำเนินการ bitwise บนif (value === null | value === undefined) return '';typo หรือคุณลักษณะจริง ๆ ถ้าใช่ทำไมใช้อันนั้นไม่ใช่แบบธรรมดา||? ขอบคุณ!!
Alejandro Vales

1
@AlejandroVales ฉันค่อนข้างแน่ใจว่ามันเป็นตัวพิมพ์ผิด ... ถูกต้อง
Tracker1

1
อย่างไรก็ตามโปรดทราบว่า | จะนำไปสู่ ​​0 หรือ 1 ดังนั้นจริงๆแล้วมันใช้งานได้ ^^
Alejandro Vales

คุณใช้== nullไม่ได้เหรอ undefinedเป็นสิ่งเดียวที่มีความเท่าเทียมnullดังนั้นจึงไม่จำเป็นต้องมีสองสามเท่า
Hashbrown

นั่นไม่จริงเลย nullและ0ทั้งสองเป็นเท็จใช่คุณทำไม่!valueได้ แต่ประเด็นทั้งหมด==คือทำให้บางสิ่งง่ายขึ้น 0 == nullเป็นเท็จ undefined == nullเป็นความจริง. คุณสามารถทำได้value == null
Hashbrown

3

เท่าที่ฉันรู้ไม่มีวิธีการเข้ารหัส / ถอดรหัส HTML ตรงไปตรงมาใน javascript

อย่างไรก็ตามสิ่งที่คุณสามารถทำได้คือการใช้ JS เพื่อสร้างองค์ประกอบโดยพลการตั้งค่าข้อความภายในจากนั้นอ่านมันโดยใช้ innerHTML

สมมติว่าด้วย jQuery สิ่งนี้ควรจะได้ผล:

var helper = $('chalk & cheese').hide().appendTo('body');
var htmled = helper.html();
helper.remove();

หรือบางสิ่งบางอย่างตามสายเหล่านี้


ฉันพบว่า downvote สนุกเล็กน้อยการพิจารณาคำตอบนี้เกือบจะเหมือนกันกับที่มีมากกว่า 870 upvote และโพสต์เล็กน้อยหลังจากนี้
Ken Egozi

2

คุณไม่จำเป็นต้องหลบหนี / เข้ารหัสค่าเพื่อส่งพวกเขาจากช่องใส่หนึ่งไปยังอีก

<form>
 <input id="button" type="button" value="Click me">
 <input type="hidden" id="hiddenId" name="hiddenId" value="I like cheese">
 <input type="text" id="output" name="output">
</form>
<script>
    $(document).ready(function(e) {
        $('#button').click(function(e) {
            $('#output').val($('#hiddenId').val());
        });
    });
</script>

JS ไม่ไปแทรก HTML ดิบหรืออะไรเลย มันเพิ่งบอกให้ DOM ตั้งค่าvalueคุณสมบัติ (หรือแอตทริบิวต์; ไม่แน่ใจ) ไม่ว่าจะด้วยวิธีใด DOM จะจัดการกับปัญหาการเข้ารหัสสำหรับคุณ นอกจากว่าคุณกำลังทำสิ่งแปลก ๆ เช่นการใช้document.writeหรือevalการเข้ารหัส HTML จะโปร่งใสอย่างมีประสิทธิภาพ

หากคุณกำลังพูดถึงการสร้างกล่องข้อความใหม่เพื่อเก็บผลลัพธ์ ... มันยังคงเป็นเรื่องง่าย เพียงผ่านส่วนคงที่ของ HTML ไปที่ jQuery แล้วตั้งค่าคุณสมบัติ / คุณสมบัติที่เหลือบนวัตถุที่ส่งคืนให้คุณ

$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());

2

ฉันมีปัญหาที่คล้ายกันและแก้ไขโดยใช้ฟังก์ชั่นencodeURIComponentจาก JavaScript ( เอกสารประกอบ )

ตัวอย่างเช่นในกรณีของคุณถ้าคุณใช้:

<input id='hiddenId' type='hidden' value='chalk & cheese' />

และ

encodeURIComponent($('#hiddenId').attr('value'))

chalk%20%26%20cheeseคุณจะได้รับ แม้กระทั่งช่องว่างจะถูกเก็บไว้

ในกรณีของฉันฉันต้องเข้ารหัสแบ็กสแลชหนึ่งรหัสและรหัสนี้ทำงานได้อย่างสมบูรณ์

encodeURIComponent('name/surname')

และฉันได้ name%2Fsurname


2

นี่เป็นเพียงเล็กน้อยที่เลียนแบบServer.HTMLEncodeฟังก์ชั่นจาก ASP ของ Microsoft ที่เขียนด้วย JavaScript บริสุทธิ์:

function htmlEncode(s) {
  var ntable = {
    "&": "amp",
    "<": "lt",
    ">": "gt",
    "\"": "quot"
  };
  s = s.replace(/[&<>"]/g, function(ch) {
    return "&" + ntable[ch] + ";";
  })
  s = s.replace(/[^ -\x7e]/g, function(ch) {
    return "&#" + ch.charCodeAt(0).toString() + ";";
  });
  return s;
}

ผลลัพธ์ไม่ได้เข้ารหัส apostrophes แต่เข้ารหัสพิเศษ HTML อื่น ๆ และอักขระใด ๆ ที่อยู่นอกช่วง 0x20-0x7e



1

หากคุณต้องการใช้ jQuery ฉันพบสิ่งนี้:

http://www.jquerysdk.com/api/jQuery.htmlspecialchars

(ส่วนหนึ่งของปลั๊กอิน jquery.string ที่เสนอโดย jQuery SDK)

ปัญหาของ Prototype ที่ฉันเชื่อคือมันขยายวัตถุพื้นฐานใน JavaScript และจะไม่สามารถใช้ร่วมกับ jQuery ใด ๆ ที่คุณอาจใช้ แน่นอนถ้าคุณใช้ Prototype อยู่แล้วไม่ใช่ jQuery มันจะไม่มีปัญหา

แก้ไข: ยังมีสิ่งนี้ซึ่งเป็นพอร์ตของโปรแกรมอรรถประโยชน์สตริงของ Prototype สำหรับ jQuery:

http://stilldesigning.com/dotstring/


1
var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.push(echar);
            entityKeys.push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

นี่คือจากรหัสแหล่ง ExtJS


1
<script>
String.prototype.htmlEncode = function () {
    return String(this)
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');

}

var aString = '<script>alert("I hack your site")</script>';
console.log(aString.htmlEncode());
</script>

จะส่งออก: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

.htmlEncode () จะสามารถเข้าถึงได้บนสตริงทั้งหมดเมื่อกำหนดไว้แล้ว


1

HtmlEncode ค่าที่กำหนด

  var htmlEncodeContainer = $('<div />');
  function htmlEncode(value) {
    if (value) {
      return htmlEncodeContainer.text(value).html();
    } else {
      return '';
    }
  }


0

เลือกอะไร escapeHTML()กำลังทำใน prototype.js

การเพิ่มสคริปต์นี้ช่วยให้คุณสามารถหลบหนี HTML:

String.prototype.escapeHTML = function() { 
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
}

ตอนนี้คุณสามารถเรียกเมธอด escapeHTML บนสตริงในสคริปต์ของคุณเช่น:

var escapedString = "<h1>this is HTML</h1>".escapeHTML();
// gives: "&lt;h1&gt;this is HTML&lt;/h1&gt;"

หวังว่ามันจะช่วยให้ทุกคนกำลังมองหาทางออกที่ง่ายโดยไม่ต้องรวมทั้งต้นแบบ.js


0

ใช้คำตอบอื่น ๆ ที่นี่ฉันทำรุ่นที่แทนที่ตัวละครที่เกี่ยวข้องทั้งหมดในครั้งเดียวโดยไม่คำนึงถึงจำนวนของอักขระที่เข้ารหัสที่แตกต่างกัน (โทรเพียงครั้งเดียวเพื่อ replace() ) ดังนั้นจะเร็วขึ้นสำหรับสตริงขนาดใหญ่

ไม่พึ่งพา DOM API ที่มีอยู่หรือในไลบรารีอื่น ๆ

window.encodeHTML = (function() {
    function escapeRegex(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    }
    var encodings = {
        '&'  : '&amp;',
        '"'  : '&quot;',
        '\'' : '&#39;',
        '<'  : '&lt;',
        '>'  : '&gt;',
        '\\' : '&#x2F;'
    };
    function encode(what) { return encodings[what]; };
    var specialChars = new RegExp('[' +
        escapeRegex(Object.keys(encodings).join('')) +
    ']', 'g');

    return function(text) { return text.replace(specialChars, encode); };
})();

คุณสามารถโทรได้ทันที

encodeHTML('<>&"\'')

ที่จะได้รับ &lt;&gt;&amp;&quot;&#39;


0

function encodeHTML(str) {
    return document.createElement("a").appendChild( 
        document.createTextNode(str)).parentNode.innerHTML;
};

function decodeHTML(str) {
    var element = document.createElement("a"); 
    element.innerHTML = str;
    return element.textContent;
};
var str = "<"
var enc = encodeHTML(str);
var dec = decodeHTML(enc);
console.log("str: " + str, "\nenc: " + enc, "\ndec: " + dec);

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.