HttpUtility.HtmlEncode слишком много экранирования? - PullRequest
7 голосов
/ 03 февраля 2012

В нашем проекте MVC3 ASP.net метод HttpUtility.HtmlEncode, по-видимому, экранирует слишком много символов.Наши веб-страницы обслуживаются как страницы UTF-8, но метод по-прежнему экранирует такие символы, как ü или символ иены ¥, хотя эти символы являются частью набора UTF-8 .

Поэтому, когда мое представление asp.net MVC содержит следующий фрагмент кода:

    @("<strong>ümlaut</strong>")

Тогда я ожидал бы, что кодировщик экранирует теги html, но не ümlaut

    &lt;strong&gt;ümlaut&lt;/strong&gt;

Но вместо этого он дает мне следующий фрагмент HTML:

    &lt;strong&gt;&#252;mlaut&lt;/strong&gt;

Для полноты я также упомяну, что responseEncoding в web.config явно установлен в utf-8, поэтому яожидается, что метод HtmlEncode будет учитывать этот параметр.

    <globalization requestEncoding="utf-8" responseEncoding="utf-8" />

Ответы [ 3 ]

2 голосов
/ 03 февраля 2012

Да, у меня та же проблема с моими веб-страницами.Если мы видим код htmlEncode, то есть точка, которая переводит этот набор символов.Вот код, который переводил этот вид символов.

if ((ch >= '\x00a0') && (ch < 'A'))
{
    output.Write("&#");
    output.Write(ch.ToString(NumberFormatInfo.InvariantInfo));
    output.Write(';');
}
else
{
    output.Write(ch);
}

Вот код HtmlEncode

public static unsafe void HtmlEncode(string value, TextWriter output)
{
    if (value != null)
    {
        if (output == null)
        {
            throw new ArgumentNullException("output");
        }
        int num = IndexOfHtmlEncodingChars(value, 0);
        if (num == -1)
        {
            output.Write(value);
        }
        else
        {
            int num2 = value.Length - num;
            fixed (char* str = ((char*) value))
            {
                char* chPtr = str;
                char* chPtr2 = chPtr;
                while (num-- > 0)
                {
                    output.Write(chPtr2[0]);
                    chPtr2++;
                }
                while (num2-- > 0)
                {
                    char ch = chPtr2[0];
                    if (ch <= '>')
                    {
                        switch (ch)
                        {
                            case '&':
                            {
                                output.Write("&amp;");
                                chPtr2++;
                                continue;
                            }
                            case '\'':
                            {
                                output.Write("&#39;");
                                chPtr2++;
                                continue;
                            }
                            case '"':
                            {
                                output.Write("&quot;");
                                chPtr2++;
                                continue;
                            }
                            case '<':
                            {
                                output.Write("&lt;");
                                chPtr2++;
                                continue;
                            }
                            case '>':
                            {
                                output.Write("&gt;");
                                chPtr2++;
                                continue;
                            }
                        }
                        output.Write(ch);
                        chPtr2++;
                        continue;
                    }
                    // !here is the point!
                    if ((ch >= '\x00a0') && (ch < 'Ā'))
                    {
                        output.Write("&#");
                        output.Write(ch.ToString(NumberFormatInfo.InvariantInfo));
                        output.Write(';');
                    }
                    else
                    {
                        output.Write(ch);
                    }
                    chPtr2++;
                }
            }
        }
    }
}

a Возможные решения - создать свой собственный HtmlEncode или использовать AntiСкрипты для кросс-сайтов от MS.

http://msdn.microsoft.com/en-us/security/aa973814

1 голос
/ 06 февраля 2012

Как предположил Аристос, мы можем использовать библиотеку AntiXSS от Microsoft. Он содержит UnicodeCharacterEncoder , который ведет себя так, как вы ожидаете.

Но потому что мы

  • на самом деле не хотел зависеть от сторонней библиотеки только для кодирования HTML
  • были совершенно уверены, что наш контент не превысил диапазон UTF-8.

Мы решили реализовать наш собственный очень простой HTML-кодировщик. Вы можете найти код ниже. Пожалуйста, не стесняйтесь адаптировать / комментировать / улучшать, если вы видите какие-либо проблемы.

public static class HtmlEncoder
{
    private static IDictionary<char, string> toEscape = new Dictionary<char, string>()
                                                            {
                                                                { '<', "lt" },
                                                                { '>', "gt" },
                                                                { '"', "quot" },
                                                                { '&', "amp" },
                                                                { '\'', "#39" },
                                                            };
    /// <summary>
    /// HTML-Encodes the provided value
    /// </summary>
    /// <param name="value">object to encode</param>
    /// <returns>An HTML-encoded string representing the provided value.</returns>
    public static string Encode(object value)
    {
        if (value == null)
            return string.Empty;

        // If value is bare HTML, we expect it to be encoded already
        if (value is IHtmlString)
            return value.ToString();

        string toEncode = value.ToString();

        // Init capacity to length of string to encode
        var builder = new StringBuilder(toEncode.Length);

        foreach (char c in toEncode)
        {
            string result;
            bool success = toEscape.TryGetValue(c, out result);

            string character = success
                                ? "&" + result + ";"
                                : c.ToString();

            builder.Append(character);
        }

        return builder.ToString();
    }
}
0 голосов
/ 27 марта 2013

на основе ответа Томаса, немного улучшена обработка пробела, табуляции и новой строки, поскольку они могут нарушить структуру html:

public static string HtmlEncode(string value,bool removeNewLineAndTabs)
    {
        if (value == null)
            return string.Empty;

        string toEncode = value.ToString();

        // Init capacity to length of string to encode
        var builder = new StringBuilder(toEncode.Length);

        foreach (char c in toEncode)
        {
            string result;
            bool success = toEscape.TryGetValue(c, out result);

            string character = success ? result : c.ToString();

            builder.Append(character);
        }

        string retVal = builder.ToString();

        if (removeNewLineAndTabs)
        {
            retVal = retVal.Replace("\r\n", " ");
            retVal = retVal.Replace("\r", " ");
            retVal = retVal.Replace("\n", " ");
            retVal = retVal.Replace("\t", " ");
        }
        return retVal;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...