从ASP.NET中转义JavaScript特殊字符

10

以下是我ASP.NET应用程序中的C#代码:

string script = @"alert('Message head:\n\n" + CompoundErrStr + " message tail.');";
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Test", script, true);

CompoundErrStr是由SQL Server生成的错误消息(存储过程中的异常文本)。如果它包含任何表列名,它们将用单引号括起来,JavaScript在执行期间会因为单引号被视为字符串终止符而中断。

为了解决单引号问题,我将我的代码更改为以下内容:

CompoundErrStr = CompoundErrStr.Replace("'", @"\'");
string script = @"alert('Message head:\n\n" + CompoundErrStr + " message tail.');";
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Test", script, true);

现在它已经正常工作了。

然而,还有其他需要像这样转义的特殊字符吗?是否有一个可以用于此目的的.Net函数?类似于HttpServerUtility.HtmlEncode但适用于JavaScript。

编辑我使用的是.Net 3.5


2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Sreenath
@Sreenath HtmlEncode 不会对 JavaScript 字符串进行转义... - Adriano Repetti
@Joe Schmoe:如果你正在寻找一个可以对特殊字符进行编码的JS函数,你可以尝试使用JS中的"encodeURIComponent"函数。http://www.w3schools.com/jsref/jsref_encodeuricomponent.asp - Sreenath
@Sreenath:正如我在原帖中所说,我正在寻找 .Net 函数。 - Joe Schmoe
@JoeSchmoe 你可以尝试使用来自“Microsoft.Security.Application”的Encoder.HtmlCode。我们用它来阻止XSS攻击。 - Sreenath
显示剩余2条评论
3个回答

22

注意:对于这个任务,您不能(也不应该)使用HTML编码器(如HttpServerUtility.HtmlEncode()),因为HTML和JavaScript字符串的规则非常不同。例如:字符串"Check your Windows folder c:\windows"将被编码为"Check your Windows folder c:'windows",显然是错误的。此外,它遵循HTML编码规则,因此不会对\"'进行任何转义。简而言之,它是用于其他目的。


如果您的目标是ASP.NET Core.NET 5,那么您应该使用System.Text.Encodings.Web.JavaScriptEncoder类。


如果您的目标是.NET 4.x,则可以使用HttpUtility.JavaScriptStringEncode()方法。


如果您的目标是.NET 3.x和2.x

您需要对什么进行编码?一些字符必须进行转义(\"'),因为它们对JavaScript解析器具有特殊意义,而其他字符可能会干扰HTML解析,因此也应该进行转义(如果JS在HTML页面中)。您有两个选项可用于转义:JavaScript转义字符</kbd>或\uxxxx Unicode代码点(请注意,\uxxxx可以用于所有这些字符,但对于干扰HTML解析器的字符将不起作用)。

您可以手动执行此操作(使用搜索和替换),如下所示:

string JavaScriptEscape(string text)
{
    return text
        .Replace("\\", @"\u005c")  // Because it's JS string escape character
        .Replace("\"", @"\u0022")  // Because it may be string delimiter
        .Replace("'", @"\u0027")   // Because it may be string delimiter
        .Replace("&", @"\u0026")   // Because it may interfere with HTML parsing
        .Replace("<", @"\u003c")   // Because it may interfere with HTML parsing
        .Replace(">", @"\u003e");  // Because it may interfere with HTML parsing
}

当然,如果您正在将其用作转义字符,则不应对</kbd>进行转义!这种盲目替换对于未知的文本(例如来自用户的输入或可能被翻译的文本消息)非常有用。请注意,如果字符串用双引号括起来,则单引号不需要转义,反之亦然。请注意,在C#代码中保留逐字字符串,否则将在C#中执行Unicode替换,并且客户端将接收到未转义的字符串。关于干扰HTML解析的说明:现在很少需要创建<script>节点并将其注入DOM,但这是一种相当常见的技术,网络上充满了像+ "</s" + "cript>"这样的代码来解决这个问题。
注意:我说盲目转义,因为如果您的字符串包含转义序列(例如\uxxxx\t),则不应再次转义。为此,您需要围绕此代码做些技巧。
如果您的文本来自用户输入并且可能是多行的,则还应该准备好它,否则您将会得到破碎的JavaScript代码,如下所示:
alert("This is a multiline
comment");

只需将.Replace("\n", "\\n").Replace("\r", "")添加到之前的JavaScriptEscape()函数中即可。


为了完整起见:还有另一种方法,如果您对字符串进行编码Uri.EscapeDataString(),则可以使用decodeURIComponent()在JavaScript中解码它,但这更像是一个卑鄙的技巧而不是解决方案。


1
非常好的回答!你能解释一下“盲目替换”是什么意思吗? - Joe Schmoe
2
JavaScriptEscape(@"Column 1\tColumn 2") 将被转义为 "Column 1\tColumn 2",而 @"\u0032" 将变成 "\u0032",这可能不是你想要的。总之,我的意思是它会转义所有东西,所以当你写一个转义序列(然后需要字面上复制一些内容)时,你就必须在它周围进行一些诡计。 - Adriano Repetti
Uri.EscapeDataString和decodeURIComponent是我找到的唯一“解决方案”,可以将URL转换为JavaScript字符串。 - Matthew Lock

9

尽管原问题提到了.NET 3.5,但对于使用4.0及以上版本的用户,应该知道可以使用HttpUtility.JavaScriptStringEncode("string")

第二个布尔型参数指定是否在结果中包含引号(true)或不包括引号(false)。


2

太容易了:

@Html.Raw(myString)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接