当使用 jQuery.serialize() 序列化时,如何 *HTML* 对表单内容进行编码?
How can I *HTML*-encode form contents when serializing with jQuery.serialize()?
jQuery表单.serialize()方法将表单内容序列化为字符串并自动URL-编码字符串。然后我的服务器反转这个过程并在反序列化时 URL-解码字符串。
但是我需要能够做的是HTML-在表单出现之前对表单内容进行编码序列化。换句话说,如果用户在我的表单中的文本输入中输入 HTML,我希望使用 HTML 编码使其安全,然后完全按照上述方式传输(使用 URL-正常编码)。
让我举个例子来说明:
当前使用 .serialize() 的实现
- User enters
My name is <b>Fred</b>
into a form input with name Details
.
.serialize()
serializes this as Details=My+name+is+%3Cb%3EFred%3C%2Fb%3E
(URL-encoding)
- The server deserializes the string and gets
My name is <b>Fred</b>
(URL-decoding)
我想要发生的事情
- User enters
My name is <b>Fred</b>
into a form input with name Details
.
- This gets HTML-encoded to
My name is <b>Fred</b>
(HTML-encoding)
.serialize()
serializes this as Details=My+name+is+%26lt%3Bb%26gt%3BFred%26lt%3B%2Fb%26gt%3B
(URL-encoding)
- The server URL-decodes the string and gets
My name is <b>Fred</b>
(URL-decoding only)
我希望 .serialize()
可以使用一个参数来指定表单内容应该是 HTML 编码的,但没有这样的运气。其他几个可能的解决方案是:
- 在调用
.serialize()
之前遍历表单输入并 HTML 对它们进行编码 "by hand":我宁愿不必这样做,因为它会使代码更混乱和更少健壮。
- 修改我的服务器以接受非 HTML 编码的值:出于各种原因我不会深入讨论这是有问题的而不是实际的解决方案。
有没有更简单的解决方案?
默认情况下,输入值将始终进行编码。正如您所说,您必须遍历每个值才能首先解码。您可以使用以下 jQuery 片段来执行此操作:
$('<div/>').html(value).text();
字符串必须 html 编码 在任何其他更改 之后,例如 url 编码或 sql 字符串转义。
所以你首先序列化你的字符串,在链接中使用它,然后在反序列化你html-编码它。像以前一样做,但使用下面的功能。
为什么这么重要?
因为我可以自己在 url 中输入一个非 html 转义的字符串,然后可以将其提供给您。你会认为它已经逃脱了,但事实并非如此。解决方案是在页面上打印之前将其转义。
这个问题描述了如何html-转义一个字符串:HtmlSpecialChars equivalent in Javascript?
function escapeHtml(text) {
var map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
当您使用 MVC(见评论)时,只需在需要它的单个 属性 上方应用 [AllowHtml]
属性。
您需要添加以下 using
语句(如果不存在):
using System.Web.Mvc;
注意:如果您还使用 MetadataTypeAttribute
它可能无法开箱即用(但在这种情况下不太可能成为问题)
更新
根据评论,由于您无法修改表单数据属性(动态表单),您可以在控制器中使用以下控制器操作将其关闭
[ValidateInput(false)]
您还可以更改整个服务器的设置(安全性较低)。请参阅此博客条目:
http://weblogs.asp.net/imranbaloch/handling-validateinputattribute-globally
解决方案是使用 jQuery 的 .serializeArray()
并将 HTML 编码应用于循环中的每个元素。
换句话说,我不得不改变这个:
$.ajax({
url: form.attr('action'),
async: false,
type: 'POST',
data: form.serialize(),
success: function (data) {
//...
}
});
对此:
// HTML-encode form values before submitting
var data = {};
$.each(form.serializeArray(), function() {
data[this.name] = this.value
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
});
$.ajax({
url: form.attr('action'),
async: false,
type: 'POST',
data: data,
success: function (data) {
//...
}
});
一个选项可能是直接更新 jquery 库并在 uriEncode 发生之前对 dom 值调用 htmlEncode。
我在 ASP.NET/MVC 应用程序中对此进行了测试,我在 jquery-1.8.2.js 中更新的行(第 7222 行,取决于版本)是:
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
到
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( htmlEncode(value) );
使用您认为合适但似乎有效的任何 htmlEncode 方法。
扩展此方法并调用执行 htmlEncode 的 customSerialize 方法实际上可能更有意义。
我相信这是最简单的方法,意味着您不必在调用序列化之前遍历 dom。
jQuery表单.serialize()方法将表单内容序列化为字符串并自动URL-编码字符串。然后我的服务器反转这个过程并在反序列化时 URL-解码字符串。
但是我需要能够做的是HTML-在表单出现之前对表单内容进行编码序列化。换句话说,如果用户在我的表单中的文本输入中输入 HTML,我希望使用 HTML 编码使其安全,然后完全按照上述方式传输(使用 URL-正常编码)。
让我举个例子来说明:
当前使用 .serialize() 的实现
- User enters
My name is <b>Fred</b>
into a form input with nameDetails
..serialize()
serializes this asDetails=My+name+is+%3Cb%3EFred%3C%2Fb%3E
(URL-encoding)- The server deserializes the string and gets
My name is <b>Fred</b>
(URL-decoding)
我想要发生的事情
- User enters
My name is <b>Fred</b>
into a form input with nameDetails
.- This gets HTML-encoded to
My name is <b>Fred</b>
(HTML-encoding).serialize()
serializes this asDetails=My+name+is+%26lt%3Bb%26gt%3BFred%26lt%3B%2Fb%26gt%3B
(URL-encoding)- The server URL-decodes the string and gets
My name is <b>Fred</b>
(URL-decoding only)
我希望 .serialize()
可以使用一个参数来指定表单内容应该是 HTML 编码的,但没有这样的运气。其他几个可能的解决方案是:
- 在调用
.serialize()
之前遍历表单输入并 HTML 对它们进行编码 "by hand":我宁愿不必这样做,因为它会使代码更混乱和更少健壮。 - 修改我的服务器以接受非 HTML 编码的值:出于各种原因我不会深入讨论这是有问题的而不是实际的解决方案。
有没有更简单的解决方案?
默认情况下,输入值将始终进行编码。正如您所说,您必须遍历每个值才能首先解码。您可以使用以下 jQuery 片段来执行此操作:
$('<div/>').html(value).text();
字符串必须 html 编码 在任何其他更改 之后,例如 url 编码或 sql 字符串转义。
所以你首先序列化你的字符串,在链接中使用它,然后在反序列化你html-编码它。像以前一样做,但使用下面的功能。
为什么这么重要?
因为我可以自己在 url 中输入一个非 html 转义的字符串,然后可以将其提供给您。你会认为它已经逃脱了,但事实并非如此。解决方案是在页面上打印之前将其转义。
这个问题描述了如何html-转义一个字符串:HtmlSpecialChars equivalent in Javascript?
function escapeHtml(text) {
var map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
当您使用 MVC(见评论)时,只需在需要它的单个 属性 上方应用 [AllowHtml]
属性。
您需要添加以下 using
语句(如果不存在):
using System.Web.Mvc;
注意:如果您还使用 MetadataTypeAttribute
它可能无法开箱即用(但在这种情况下不太可能成为问题)
更新
根据评论,由于您无法修改表单数据属性(动态表单),您可以在控制器中使用以下控制器操作将其关闭
[ValidateInput(false)]
您还可以更改整个服务器的设置(安全性较低)。请参阅此博客条目:
http://weblogs.asp.net/imranbaloch/handling-validateinputattribute-globally
解决方案是使用 jQuery 的 .serializeArray()
并将 HTML 编码应用于循环中的每个元素。
换句话说,我不得不改变这个:
$.ajax({
url: form.attr('action'),
async: false,
type: 'POST',
data: form.serialize(),
success: function (data) {
//...
}
});
对此:
// HTML-encode form values before submitting
var data = {};
$.each(form.serializeArray(), function() {
data[this.name] = this.value
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
});
$.ajax({
url: form.attr('action'),
async: false,
type: 'POST',
data: data,
success: function (data) {
//...
}
});
一个选项可能是直接更新 jquery 库并在 uriEncode 发生之前对 dom 值调用 htmlEncode。
我在 ASP.NET/MVC 应用程序中对此进行了测试,我在 jquery-1.8.2.js 中更新的行(第 7222 行,取决于版本)是:
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
到
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( htmlEncode(value) );
使用您认为合适但似乎有效的任何 htmlEncode 方法。
扩展此方法并调用执行 htmlEncode 的 customSerialize 方法实际上可能更有意义。
我相信这是最简单的方法,意味着您不必在调用序列化之前遍历 dom。