给定一个 URL 的 Web 表单中的任意客户输入,我想生成一个包含该 URL 的新 HTML 文档 href
.我的问题是我应该如何在我的 HTML 中保护该 URL。
对于未知最终用户输入的以下 URL,应该将什么呈现到 HTML 中:
-
http://example.com/?file=some_19%affordable.txt
-
http://example.com/url?source=web&last="f o o"&bar=<
-
https://www.google.com/url?source=web&sqi=2&url=https%3A%2F%2Ftwitter.com%2F%3Flang%3Den&last=%22foo%22
如果我们假设 URL 已经进行了 uri 编码,我认为如果他们从 URL 栏复制它是合理的,那么只需将它传递给 attr()
生成通过 validator.w3.org/nu 的 Nu HTML 检查器的有效 URL 和文档。
为了查看实际效果,我们在 https://jsfiddle.net/kamelkev/w8ygpcsz/2/ 设置了一个 JS fiddle用上面的示例替换其中的 URL 可以显示正在发生的事情。
为了将来引用,这包含一个 HTML 片段
<a>My Link</a>
和这个 JS:
$(document).ready(function() {
$('a').attr('href', 'http://example.com/request.html?data=>');
$('a').attr('href2', 'http://example.com/request.html?data=<');
alert($('a').get(0).outerHTML);
});
因此对于 URL 1,不可能通过机械地查看它来判断它是否经过 URI 编码。你可以根据你的人类知识推测它不是,它指的是一个名为 some_19%affordable.txt
的文件。 .当运行 fiddle 时,它产生
<a href="http://example.com/?file=some_19%affordable.txt">My Link</a>
它可以毫无问题地通过 HTML5 验证程序。不过,这可能不是用户的意图。
第二个 URL 显然不是 URI 编码的。问题变成了将什么东西放入 HTML 中以防止 HTML 解析问题是正确的。
通过 fiddle 运行它,Safari 10 产生了这个:
<a href="http://example.com/url?source=web&last="f o o"&bar=<">My Link</a>
几乎所有其他浏览器都会产生这个:
<a href="http://example.com/url?source=web&last="f o o"&bar=<">My Link</a>
这些都没有通过验证器。三种投诉是可能的:文字双引号(来自未转义的 HTML)、空格或结尾的 <
字符(也来自未转义的 HTML)。它只是向您展示它找到的第一个。这显然不是有效的 HTML。
尝试解决此问题的两种方法是 a) 在将 URL 提供给 attr()
之前对 URL 进行 html 转义.然而,这导致每个 &
成为&
以及 &
等实体和 <
被 attr()
双重转义,文档中的 URL 完全不准确。它看起来像这样:
<a href="http://example.com/url?source=web&amp;last=&quot;f+o+o&quot;&amp;bar=&lt;">My Link</a>
另一种是在传递给 attr()
之前对其进行 URI 编码,这确实会产生一个正确的验证 URL,该 URL 实际上会点击到预期的目的地。它看起来像这样:
<a href="http://example.com/url?source=web&last=%22f%20o%20o%22&bar=%3C">My Link</a>
最后,对于经过正确 URI 编码的第三个 URL,验证的正确 HTML 确实出现了。
<a href="https://www.google.com/url?source=web&sqi=2&url=https%3A%2F%2Ftwitter.com%2F%3Flang%3Den&last=%22foo%22">My Link</a>
它会执行用户希望在点击时发生的事情。
基于此,算法应该是:
if url is encoded then
pass as-is to attr()
else
pass encodeURI(url) to attr()
但是,根据这两个先前的讨论,“已编码”测试似乎无法肯定地检测到(实际上,请参见示例 URL 1):
How to find out if string has already been URL encoded? How to know if a URL is decoded/encoded?
如果我们绕过 attr()
方法并强制将示例 URL 2 的 HTML 转义版本插入到文档结构中,它看起来像这样:
<a href="http://example.com/url?source=web&last="f+o+o"&bar=<">My Link</a>
这看起来像有效的 HTML,但未能通过 HTML5 验证器,因为它无法转义为具有无效的 URL 字符。然而,浏览器似乎并不介意。不幸的是,如果您对该对象进行任何其他操作,浏览器将重新转义所有 &
无论如何。
如您所见,这一切都非常令人困惑。这是我们第一次使用浏览器本身生成 HTML,我们不确定是否正确。以前,我们使用模板在服务器端完成,并且只做了 HTML 转义过滤器。
安全准确插入用户提供的正确方法是什么 将 URL 数据转换为 HTML5 文档(使用 JavaScript)?
最佳答案
如果您可以假设 URL 已编码或未编码,那么您或许可以按照此思路逃避某些问题。尝试解码 URL,将错误视为 URL 未编码,您应该留下解码后的 URL。
<script>
var inputurl = 'http://example.com/?file=some_19%affordable.txt';
var myurl;
try {
myurl = decodeURI(inputurl);
}
catch(error) {
myurl = inputurl;
}
console.log(myurl);
</script>
关于javascript - 安全准确地将用户提供的 URL 数据插入 HTML5 文档的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39795859/