programing

일반 자바에서 HTML 기호를 이스케이프하는 방법은?

prostudy 2022. 5. 22. 11:23
반응형

일반 자바에서 HTML 기호를 이스케이프하는 방법은?

탈출할 수 있는 추천 방법이 있는가?<,>,"그리고&일반 Java 코드로 HTML을 출력할 때 문자(수동으로 다음 작업을 수행하지 않는 경우)

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

Apache Commons LangStringEscapeUtils:

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);

Apache Commons의 대안:스프링스 사용HtmlUtils.htmlEscape(String input)방법의

간단한 방법:

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가 빠져 있다.http://www.w3.org/TR/html4/sgml/entities.html에 따르면 if 절에서 체크한 4개의 문자는 128개 이하의 문자뿐이라고 한다.

Apache Commons Lang 라이브러리의 최신 버전이 있으며 다른 패키지 이름(org.apache.commons.lang3)을 사용한다.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");

Google Guava를 사용하는 사용자:

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);

Android(API 16 이상):

Html.escapeHtml(textToScape);

또는 낮은 API의 경우:

TextUtils.htmlEncode(textToScape);

이거 조심해.HTML 문서에는 다음과 같은 다양한 '컨텍스트'가 있다.요소 내부, 인용된 속성 값, 인용되지 않은 속성 값, URL 속성, javascript, CSS 등...사이트 간 스크립팅(XSS)을 방지하려면 각각 다른 인코딩 방법을 사용해야 한다.각 컨텍스트에 대한 자세한 내용은 OWASP XSS Prevention 커트 시트를 참조하십시오.OWASP ESAPI 라이브러리 https://github.com/ESAPI/esapi-java-legacy에서 이러한 각 컨텍스트에 대한 탈출 방법을 찾을 수 있다.

HTMLUtils:

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

org.properties.properties.cnStringEscapeUtils는 이제 더 이상 사용되지 않는다.이제 org.apache.commons.text를 사용해야 한다.StringEscapeUtils 기준

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

@dfa가 대답하는 동안org.apache.commons.lang.StringEscapeUtils.escapeHtml멋지고 나는 그것을 HTML (또는 XML) 속성의 탈출에 사용해서는 안 된다. 그렇지 않으면 공백이 정규화된다(즉, 인접한 모든 공백 문자는 하나의 공간이 된다).

공백이 보존되지 않은 속성에 대해 라이브러리(JATL)에 버그를 저장했기 때문에 나는 이것을 알고 있다.그러므로 나는 속성과 요소 내용의 탈출을 구별하는 (그 중 일부를 JDOM에서 훔쳤다) 클래스에 한 방울이 있다.

과거에는 이것이 그다지 중요하지 않았을 수도 있지만(속성 속성 탈출) HTML5의 사용을 고려할 때 점점 더 큰 관심을 갖게 되고 있다.data-속성 용법

Java 8+ 솔루션:

public static String escapeHTML(String str) {
    return str.chars().mapToObj(c -> c > 127 || "\"'<>&".indexOf(c) != -1 ?
       "&#" + c + ";" : String.valueOf((char) c)).collect(Collectors.joining());
}

String#chars a를 반환하다.IntStream문자열의 문자 값.그러면 우리는 사용할 수 있다.mapToObj문자 코드가 127(비 ASC) 이상인 문자를 이스케이프하려면는 물론 Ⅱ 文字)은 十和田(이중인문)도다.")), 단일 인용문 (' 괄호()), 좌측도 브래킷(브래킷)<()), 우측도 브래킷(브래킷)> 및 앰퍼샌드(암퍼샌드)&).Collectors.joining…을 연결하다String다시 합치다

유니코드 문자를 더 잘 처리하려면String#codePoints대신 사용할 수 있다.

public static String escapeHTML(String str) {
    return str.codePoints().mapToObj(c -> c > 127 || "\"'<>&".indexOf(c) != -1 ?
            "&#" + c + ";" : new String(Character.toChars(c)))
       .collect(Collectors.joining());
}

대부분의 도서관은 수백 개의 상징과 수천 개의 비ASC를 포함한 그들이 할 수 있는 모든 것을 탈출을 제공한다.UTF-8 세계에서는 당신이 원하는 것이 아닌 II 캐릭터.

또한, 제프 윌리엄스가 언급했듯이, "도피 HTML" 옵션은 단 한 가지도 없으며, 몇 가지 맥락도 있다.

인용되지 않은 속성을 사용하지 않는다고 가정하고 다른 컨텍스트가 존재한다는 점을 염두에 두고 나만의 버전을 작성했다.

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

// '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;";
private static final int REPL_SLICES = /*  [0,   5,   10,  15, 19) */
        5<<5 | 10<<10 | 15<<15 | 19<<20;
// These 5-bit numbers packed into a single int
// are indices within REPLACEMENTS which is a 'flat' String[]

private static void appendEscaped(
        Appendable builder, CharSequence content, long escapes) {
    try {
        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(ESCAPES & (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);
    } catch (IOException e) {
        // typically, our Appendable is StringBuilder which does not throw;
        // also, there's no way to declare 'if A#append() throws E,
        // then appendEscaped() throws E, too'
        throw new UncheckedIOException(e);
    }
}

줄 길이 제한 없이 Gist에서 복사 붙여넣기를 고려하십시오.

UPD: 다른 답변에서 알 수 있듯이,>탈출은 필요하지 않다. 또한,"안쪽에attr='…'그것도 허용된다.나는 그에 따라 코드를 업데이트했다.

직접 확인해 보십시오.

<!DOCTYPE html>
<html lang="en">
<head><title>Test</title></head>
<body>

<p title="&lt;&#34;I'm double-quoted!&#34;>">&lt;"Hello!"></p>
<p title='&lt;"I&#39;m single-quoted!">'>&lt;"Goodbye!"></p>

</body>
</html>

참조URL: https://stackoverflow.com/questions/1265282/what-is-the-recommended-way-to-escape-html-symbols-in-plain-java

반응형