जावा में HTML से बचने के लिए अनुशंसित विधि


262

वहाँ से बचने के लिए एक सिफारिश रास्ता नहीं है <, >, "और &सादे जावा कोड में पात्रों जब outputting एचटीएमएल? (निम्नलिखित को मैन्युअल रूप से करने के अलावा, वह है)।

String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML";
String escaped = source.replace("<", "&lt;").replace("&", "&amp;"); // ...

2
इस बात से अवगत रहें कि यदि आप एक अनकॉट किए गए HTML विशेषता में आउटपुट कर रहे हैं, तो अन्य वर्ण जैसे कि स्पेस, टैब, बैकस्पेस, आदि ... हमलावरों को सूचीबद्ध वर्णों के बिना जावास्क्रिप्ट विशेषताओं को पेश करने की अनुमति दे सकते हैं। अधिक के लिए OWASP XSS प्रिवेंशन चीट शीट देखें।
जेफ विलियम्स

BTW, इस कोड में, आपको ठीक से काम करने के लिए "<" से पहले "&" से बचना चाहिए ("& lt;" को "& lt;" से बदला जाए, अन्यथा "& lt;" के रूप में रेंडर किया गया है, फिर नहीं] "):source.replace("&", "&amp;").replace("<", "&lt;");
Tey '23

जवाबों:


261

StringEscapeUtils से अपाचे कॉमन्स लैंग :

import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
// ...
String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML";
String escaped = escapeHtml(source);

के लिए 3 संस्करण :

import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
// ...
String escaped = escapeHtml4(source);

2
जबकि StringEscapeUtilsअच्छा है यह विशेषताओं के लिए ठीक से खाली स्थान के बच नहीं होगा यदि आप HTML / एक्सएमएल खाली स्थान के सामान्यीकरण से बचने के लिए चाहते हैं। अधिक विवरण के लिए मेरा उत्तर देखें।
एडम जेंट

21
उपरोक्त उदाहरण टूट गया है। अब एस्केपHtml4 () विधि का उपयोग करें।
stackoverflowuser2010

3
अमरूद के प्रशंसकों के लिए नीचे okranz का उत्तर देखें।
जॉर्ज हॉकिन्स

2
यदि वेबपेज में UTF-8 एन्कोडिंग है, तो हमें केवल अमरूद का HTMLEscaper चाहिए जो केवल निम्नलिखित पांच ASCII वर्णों से बचता है: '' & <>> Apache's esHtml () गैर-ASCII वर्णों को भी बदलता है, जिसमें एक्सेंट शामिल हैं जो UTF-8 वेब के साथ अनावश्यक लगता है। पेज?
zdenekca

4
अब इसे कॉमन्स-लैंग 3 में पदावनत किया गया है। इसे commons.apache.org/proper/commons-text
Danny

137

अपाचे कॉमन्स के लिए एक विकल्प: स्प्रिंग की HtmlUtils.htmlEscape(String input)विधि का उपयोग करें ।


9
धन्यवाद। मैं इसे (के बजाय का उपयोग किया है StringEscapeUtils.escapeHtml()से apache-commons2.6) क्योंकि यह है के रूप में रूसी वर्ण छोड़ देता है।
स्लाव सेमीशिन

6
यह जानकर अच्छा लगा। टीबीएच मैं अपाचे सामान को इन दिनों एक विस्तृत बर्थ देता हूं।
एडम्सकी जूल

1
मैंने भी इसका इस्तेमाल किया है, यह भी चीनी पात्रों को छोड़ देता है, जैसे भी है।
smartwjw

नीचे वर्णित अमरूद विकल्प के साथ इसकी तुलना कैसे की जाती है?
vishvAs vAsuki

2
और यह एपोस्ट्रोफ को भी एनकोड करता है, इसलिए यह वास्तव में उपयोगी है, Apache StringEscapeUtils के विपरीत
डेविड बालैसिक

57

अच्छी छोटी विधि:

public static String escapeHTML(String s) {
    StringBuilder out = new StringBuilder(Math.max(16, s.length()));
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (c > 127 || c == '"' || c == '\'' || c == '<' || c == '>' || c == '&') {
            out.append("&#");
            out.append((int) c);
            out.append(';');
        } else {
            out.append(c);
        }
    }
    return out.toString();
}

Https://stackoverflow.com/a/8838023/1199155 के आधार पर (वहां amp गायब है)। यदि चार खंडों में चेक किए गए चार अक्षर 128 से नीचे वाले हैं, तो http://www.w3.org/TR/html4/sgml/entities.html के अनुसार


अच्छा लगा। यह एन्कोडिंग्स के "html संस्करणों" का उपयोग नहीं करता है (उदाहरण: "á" होगा "& aacute;" के बजाय "& # 225;"), लेकिन चूंकि संख्यात्मक IE IE7 में भी काम करते हैं, मुझे लगता है कि मैं नहीं परेशान होना पड़ता है। धन्यवाद।
nonzaprej

जब आप ओपी को 4 प्रासंगिक पात्रों से बचने के लिए कहते हैं तो आप सभी पात्रों को क्यों एन्कोड करते हैं? आप CPU और मेमोरी को बर्बाद कर रहे हैं।
डेविड बालैसिक

1
आप एपोस्ट्रोफ़ भूल गए। इसलिए लोग हर जगह अयोग्य विशेषताओं को इंजेक्ट कर सकते हैं जहां यह कोड विशेषता मूल्यों से बचने के लिए उपयोग किया जाता है।
डेविड बालैसिक

45

अपाचे कॉमन्स लैंग लाइब्रेरी का एक नया संस्करण है और यह एक अलग पैकेज नाम (org.apache.commons.ln3) का उपयोग करता है। StringEscapeUtilsअब दस्तावेजों के विभिन्न प्रकार से बचने के लिए अलग अलग तरीकों स्थिर है ( http://commons.apache.org/proper/commons-lang/javadocs/api-3.0/index.html )। तो HTML संस्करण 4.0 स्ट्रिंग से बचने के लिए:

import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;

String output = escapeHtml4("The less than sign (<) and ampersand (&) must be escaped before using them in HTML");

3
दुर्भाग्य से एचटीएमएल 5 के लिए कुछ भी मौजूद नहीं है, और न ही अपाचे दस्तावेज निर्दिष्ट करते हैं कि क्या एचटीएमएल 5 के लिए एस्केपहेटलएम 4 का उपयोग करना उचित है
पॉल विंसेंट

43

Google अमरूद का उपयोग करने वालों के लिए:

import com.google.common.html.HtmlEscapers;
[...]
String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML";
String escaped = HtmlEscapers.htmlEscaper().escape(source);

40

Android पर (API 16 या अधिक) आप कर सकते हैं:

Html.escapeHtml(textToScape);

या निम्न API के लिए:

TextUtils.htmlEncode(textToScape);

क्या escapeHtmlइसके बजाय उपयोग करने का कोई कारण है htmlEncode?
मुज

2
इन दोनों के अंतर के बारे में मेरा प्रश्न भी देखें । (@Muz)
जोनासकज - मोनिका

37

इससे सावधान रहें। HTML डॉक्यूमेंट के भीतर कई अलग-अलग 'संदर्भ' होते हैं: एक तत्व के अंदर, उद्धृत विशेषता मान, अनक्लेटेड एट्रीब्यूट वैल्यू, URL विशेषता, जावास्क्रिप्ट, सीएसएस, आदि ... आपको प्रत्येक आईडी के लिए एक अलग एन्कोडिंग विधि का उपयोग करने की आवश्यकता होगी क्रॉस-साइट स्क्रिप्टिंग (XSS) को रोकने के लिए ये। चेक OWASP XSS रोकथाम चीट शीट इन संदर्भों में से प्रत्येक पर जानकारी के लिए। आप OWASP ESAPI पुस्तकालय में इन संदर्भों में से प्रत्येक के लिए बचने के तरीके पा सकते हैं - https://github.com/ESAPI/esapi-java-legacy


6
यह इंगित करने के लिए धन्यवाद कि आप जिस संदर्भ में आउटपुट को बहुत अधिक महत्व देना चाहते हैं। "एनकोड" शब्द "एस्केप" की तुलना में बहुत अधिक उपयुक्त क्रिया है, साथ ही साथ। एस्केप का अर्थ किसी प्रकार की विशेष हैक से है, "मैं इसके लिए इस स्ट्रिंग को कैसे एनकोड करता हूं : एक्सएचटीएमएल विशेषता / एसक्यूएल क्वेरी पैरामीटर / पोस्टस्क्रिप्ट प्रिंट स्ट्रिंग / सीएसवी आउटपुट फ़ील्ड?
रोबोप्रोग

5
इसका वर्णन करने के लिए 'एनकोड' और 'एस्केप' दोनों का व्यापक रूप से उपयोग किया जाता है। "एस्केप" शब्द का उपयोग आम तौर पर तब किया जाता है जब प्रक्रिया को वाक्य-रचना-प्रासंगिक चरित्र से पहले "एस्केप कैरेक्टर" को जोड़ना होता है, जैसे कि बैकस्लैश \ _ "एन्कोड" शब्द के साथ एक क्वैश्चन कैरेक्टर से बचना अधिक आम तौर पर तब उपयोग होता है जब आप ट्रांसलेट करते हैं। एक अलग रूप में चरित्र, जैसे कि URL एन्कोडिंग चरित्र वर्ण 22% या HTML इकाई एन्कोडिंग के रूप में & # x22 या @quot।
जेफ विलियम्स


1
आपको कुछ गुगली
Jakub

14

कुछ उद्देश्यों के लिए, HtmlUtils :

import org.springframework.web.util.HtmlUtils;
[...]
HtmlUtils.htmlEscapeDecimal("&"); //gives &#38;
HtmlUtils.htmlEscape("&"); //gives &amp;

1
वसंत HtmlUtils टिप्पणियों से: * <p> स्ट्रिंग भागने वाले उपयोगिताओं के व्यापक सेट के लिए, * Apache Commons Lang और उसके StringEscapeUtils वर्ग पर विचार करें। * हम उस समय का उपयोग नहीं कर रहे हैं ताकि रनटाइम निर्भरता से बचा जा सके * केवल HTML से बचने के लिए कॉमन्स लैंग पर। इसके अलावा, स्प्रिंग का * HTML बचना अधिक लचीला और 100% HTML 4.0 अनुरूप है। यदि आप पहले से ही अपाचे कॉमन्स का उपयोग अपनी परियोजना में कर रहे हैं, तो शायद आपको अपाचे से स्ट्रिंगरस्केप यूटिल्स का उपयोग करना चाहिए
andreyro

10

जबकि @dfa का उत्तर org.apache.commons.lang.StringEscapeUtils.escapeHtmlअच्छा है और मैंने इसे अतीत में इस्तेमाल किया है इसे HTML (या XML) विशेषताओं से बचने के लिए उपयोग नहीं किया जाना चाहिए अन्यथा व्हाट्सएप सामान्यीकृत हो जाएगा (जिसका अर्थ है कि सभी आसन्न व्हाट्सएप वर्ण एकल स्थान बन जाते हैं)।

मुझे यह पता है क्योंकि मैंने अपने पुस्तकालय (जेएटीएल) के खिलाफ उन विशेषताओं के लिए बग दर्ज किया है जहां व्हाट्सएप संरक्षित नहीं था। इस प्रकार मेरे पास ड्रॉप (कॉपी n 'पेस्ट) वर्ग है (जिनमें से मैंने JDOM से कुछ चुराया है) जो विशेषताओं और तत्व सामग्री के भागने को अलग करता है

हालांकि यह अतीत (उचित विशेषता से बचना) में उतना अधिक मायने नहीं रखता है, यह HTML5 के data-विशेषता उपयोग के उपयोग को देखते हुए अधिक से अधिक ब्याज बन रहा है ।


9

org.apache.commons.lang3.StringEscapeUtils अब हटा दिया गया है। अब आपको org.apache.commons.text.StringEscapeUtils का उपयोग करना चाहिए

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-text</artifactId>
        <version>${commons.text.version}</version>
    </dependency>

1

सबसे अधिक पुस्तकालय उन सभी चीजों से बचने की पेशकश करते हैं, जिनमें सैकड़ों प्रतीक और हजारों गैर-एएससीआईआई अक्षर शामिल हैं जो आप यूटीएफ -8 दुनिया में नहीं चाहते हैं।

इसके अलावा, जेफ विलियम्स ने कहा, कोई एकल "एस्केप HTML" विकल्प नहीं है, कई संदर्भ हैं।

यह मानते हुए कि आप कभी भी अछूता विशेषताओं का उपयोग नहीं करते हैं, और यह ध्यान में रखते हुए कि विभिन्न संदर्भ मौजूद हैं, इसने मेरा अपना संस्करण लिखा है:

private static final long BODY_ESCAPE =
        1L << '&' | 1L << '<' | 1L << '>';
private static final long DOUBLE_QUOTED_ATTR_ESCAPE =
        1L << '"' | 1L << '&' | 1L << '<' | 1L << '>';
private static final long SINGLE_QUOTED_ATTR_ESCAPE =
        1L << '"' | 1L << '&' | 1L << '\'' | 1L << '<' | 1L << '>';

// 'quot' and 'apos' are 1 char longer than '#34' and '#39' which I've decided to use
private static final String REPLACEMENTS = "&#34;&amp;&#39;&lt;&gt;";
private static final int REPL_SLICES = /*  |0,   5,   10,  15, 19, 23*/
        5<<5 | 10<<10 | 15<<15 | 19<<20 | 23<<25;
// These 5-bit numbers packed into a single int
// are indices within REPLACEMENTS which is a 'flat' String[]

private static void appendEscaped(
        StringBuilder builder,
        CharSequence content,
        long escapes // pass BODY_ESCAPE or *_QUOTED_ATTR_ESCAPE here
) {
    int startIdx = 0, len = content.length();
    for (int i = 0; i < len; i++) {
        char c = content.charAt(i);
        long one;
        if (((c & 63) == c) && ((one = 1L << c) & escapes) != 0) {
        // -^^^^^^^^^^^^^^^   -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        // |                  | take only dangerous characters
        // | java shifts longs by 6 least significant bits,
        // | e. g. << 0b110111111 is same as >> 0b111111.
        // | Filter out bigger characters

            int index = Long.bitCount(SINGLE_QUOTED_ATTR_ESCAPE & (one - 1));
            builder.append(content, startIdx, i /* exclusive */)
                    .append(REPLACEMENTS,
                            REPL_SLICES >>> 5*index & 31,
                            REPL_SLICES >>> 5*(index+1) & 31);
            startIdx = i + 1;
        }
    }
    builder.append(content, startIdx, len);
}

लाइन लंबाई सीमा के बिना Gist से कॉपी-पेस्टिंग पर विचार करें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.