Gibt es eine Standardmethode zum Codieren einer .NET-Zeichenfolge in eine JavaScript-Zeichenfolge zur Verwendung in MS Ajax?

73

Ich versuche, die Ausgabe einer SQL Server-Ausnahme mithilfe der RegisterStartUpScriptMethode des MS ScriptManager in .NET 3.5 an den Client zu übergeben . Dies funktioniert bei einigen Fehlern einwandfrei. Wenn die Ausnahme jedoch einfache Anführungszeichen enthält, schlägt die Warnung fehl.

Ich möchte jedoch nicht nur einfachen Anführungszeichen entkommen. Gibt es eine Standardfunktion, die ich aufrufen kann, um Sonderzeichen für die Verwendung in JavaScript zu umgehen?

string scriptstring = "alert('" + ex.Message + "');";         
ScriptManager.RegisterStartupScript(this, this.GetType(), "Alert", scriptstring , true);

EDIT :

Danke @tpeczek, der Code hat fast für mich funktioniert :) aber mit einer kleinen Änderung (das Entkommen von einfachen Anführungszeichen) funktioniert es ein Vergnügen.

Ich habe meine geänderte Version hier aufgenommen ...

public class JSEncode
{
    /// <summary>
    /// Encodes a string to be represented as a string literal. The format
    /// is essentially a JSON string.
    /// 
    /// The string returned includes outer quotes 
    /// Example Output: "Hello \"Rick\"!\r\nRock on"
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static string EncodeJsString(string s)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("\"");
        foreach (char c in s)
        {
            switch (c)
            {
                case '\'':
                    sb.Append("\\\'");
                    break;
                case '\"':
                    sb.Append("\\\"");
                    break;
                case '\\':
                    sb.Append("\\\\");
                    break;
                case '\b':
                    sb.Append("\\b");
                    break;
                case '\f':
                    sb.Append("\\f");
                    break;
                case '\n':
                    sb.Append("\\n");
                    break;
                case '\r':
                    sb.Append("\\r");
                    break;
                case '\t':
                    sb.Append("\\t");
                    break;
                default:
                    int i = (int)c;
                    if (i < 32 || i > 127)
                    {
                        sb.AppendFormat("\\u{0:X04}", i);
                    }
                    else
                    {
                        sb.Append(c);
                    }
                    break;
            }
        }
        sb.Append("\"");

        return sb.ToString();
    }
}

Wie unten erwähnt - Originalquelle: hier

Rich Andrews
quelle

Antworten:

184

Hast du dir das angeschaut HttpUtility.JavaScriptStringEncode?

Russ Cam
quelle
9
Upvoted, weil es eine großartige Antwort ist - funktioniert aber nur in .NET 4
Rich Andrews
5
Ich denke, wenn es eine Framework-Funktion für eine bestimmte Aufgabe gibt (wie diese), ist sie oft zuverlässiger und genauer als die Do-it-yourself-Funktion, also ist es besser, dabei zu bleiben.
Luke
Dieser Artikel zeigt, wie man es vor .NET 4 briancaos.wordpress.com/2012/05/16/…
rdans
2
@eddy, die Frage lautet .NET 3.5, nicht 4 und dieser Code funktioniert nur in 4+. Deshalb ist es nicht die Antwort.
Rich Andrews
1
Hinweis: Für diejenigen, die nach einer Möglichkeit suchen, internationale Zeichen in maskierte Sequenzen zu codieren, funktioniert dies nicht. In dieser Frage finden Sie eine Lösung für dieses Problem.
R. Salisbury
10

Ein Problem bei dieser Funktion ist, dass keine Zeichen codiert werden, die bei der Kapselung von HTML normalerweise außerhalb des Bandes liegen. Sie hätten also Probleme, wenn Sie versuchen würden, eine Zeichenfolge "in einen Attributwert aufzunehmen, oder wenn Sie dies getan hätten Eine Zeichenfolge mit der Sequenz </script>in einem Skriptelement. Das könnte zu Script-Injection und XSS führen.

Sie könnten hinzufügen:

            case '<':
                sb.Append("\\x3C");
                break;
            case '"':
                sb.Append("\\x22");
                break;
            case '&':
                sb.Append("\\x26");
                break;

Im Allgemeinen ist es wahrscheinlich besser, einen Standard-JSON-Encoder zu verwenden, als einen eigenen JS-String-Literal-Encoder zu brauen. Auf diese Weise können Sie einen einfachen Datentyp an JS übergeben und nicht nur Zeichenfolgen.

In .NET 3.5 Sie erhalten JavaScriptSerializer , dass jedoch zur Kenntnis nehmen, während dies tut kodieren <zu \u003C(so wird der Ausgang für die Verwendung in einem geeigneten sein <script>Elemente), ist es nicht kodieren &oder ", so HTML-escaping solche Inhalte in einem notwendig wäre, um zu schließen Für XHTML-Skriptelemente wären ein Attributwert und ein CDATA-Wrapper erforderlich.

(Wie bei vielen JSON-Encodern können auch die Zeichen U + 2028 LINE SEPARATOR und U + 2029 PARAGRAPH SEPARATOR nicht codiert werden. Der obige Code funktioniert, da alle Nicht-ASCII-Zeichen maskiert werden Diese Zeichen sind in einem JS-Zeichenfolgenliteral enthalten, da JavaScript sie nicht wie eine ASCII-Newline behandelt.)

Bobince
quelle
1
Tolles Schreiben. Beachten Sie, dass dies JavaScriptSerializerauch in .NET 2 über die Out-of-Band-Version ASP.NET AJAX 1.0 ( microsoft.com/downloads/en/… ) verfügbar ist .
Bdukes
1
In diesem Fall würden Sie nicht verwenden HttpUtility.HtmlAttributeEncode(HttpUtility.JavaScriptStringEncode(unencodedString))oder HttpUtility.HtmlEncode(HttpUtility.JavaScriptStringEncode(unencodedString))abhängig vom Kontext?
Martin Brown
@MartinBrown: Sie können beide verwenden, um in das JS-in-HTML-Attribut zu injizieren, ja (obwohl es im Allgemeinen eine schlechte Idee ist, dies zu tun). Die HtmlEncodeund HtmlAttributeEncodeMethoden sind seltsamerweise benannt; Es scheint, als sollte man besser für Attributwerte und besser für Textinhalte arbeiten, aber es gibt in der Praxis keine solche Unterscheidung, gemessen an der Referenzquelle. Sie sind nur zwei willkürlich unterschiedlich implementierte HTML-Encoder.
Bobince
3

Dies ist ein alter Thread, aber Sie könnten interessiert sein, etwas über die Microsoft AntiXSS-Bibliothek zu erfahren, die über eine Javascript-Codierungsmethode verfügt, die ab .Net 2 funktioniert.

http://msdn.microsoft.com/en-gb/security/aa973814.aspx

DomBat
quelle
Dieser Link ist nicht mehr hilfreich. Können Sie es aktualisieren?
Broots Waymb
Diese Bibliothek war ziemlich alt. Verwenden Sie dieses System.Web.Security.AntiXss vielleicht?
DomBat