繁体   English   中英

将用户提供的URL数据安全准确地插入HTML5文档的正确方法是什么?

[英]What is the right way to safely and accurately insert user-provided URL data into an HTML5 document?

给定URL的Web表单中的任意客户输入,我想在href生成包含该URL的新HTML文档。 我的问题是我应该如何在HTML中保护该URL。

对于未知最终用户输入的以下URL,应该在HTML中呈现的内容:

  1. http://example.com/?file=some_19%affordable.txt
  2. http://example.com/url?source=web&last="foo"&bar=<
  3. 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()会产生一个有效的URL和文档,它在验证器处传递Nu HTML检查器。 w3.org/nu。

为了看到它的实际效果,我们在https://jsfiddle.net/kamelkev/w8ygpcsz/2/设置了一个JS小提琴,用这些例子替换其中的URL可以显示正在发生的事情。

为了将来参考,这包含一个HTML代码段

<a>My Link</a>

这个JS:

$(document).ready(function() {
 $('a').attr('href', 'http://example.com/request.html?data=&gt;');
 $('a').attr('href2', 'http://example.com/request.html?data=<');
 alert($('a').get(0).outerHTML);
});

因此,对于URL 1,通过机械方式查看它是不可能判断它是否是URI编码的。 您可以根据您的人类知识猜测它不是,并且指的是名为some_19%affordable.txt的文件。 当它通过小提琴时,会产生

<a href="http://example.com/?file=some_19%affordable.txt">My Link</a>

哪个传递HTML5验证器没问题。 它可能不是用户想要的。

第二个URL显然不是URI编码的。 问题变成了什么是放入HTML以防止HTML解析问题的正确方法。

通过小提琴运行它,Safari 10产生这个:

<a href="http://example.com/url?source=web&amp;last=&quot;f o o&quot;&amp;bar=&lt;">My Link</a>

几乎所有其他浏览器都会产生这样的:

<a href="http://example.com/url?source=web&amp;last=&quot;f o o&quot;&amp;bar=<">My Link</a>

这些都没有通过验证器。 可能有三种抱怨:文字双引号(来自未转义的HTML),空格或尾随<字符(也来自未转义的HTML)。 它只是向您展示它找到的第一个。 这显然不是有效的HTML。

尝试解决此问题的两种方法是a)在将URL提供给attr()之前对URL进行html-escape。 然而,这导致每一个&成为&amp; 以及&amp;等实体 &lt; attr()双重转义,文档中的URL完全不准确。 它看起来像这样:

<a href="http://example.com/url?source=web&amp;amp;last=&amp;quot;f+o+o&amp;quot;&amp;amp;bar=&amp;lt;">My Link</a>

另一种是在传递给attr()之前对其进行URI编码,这会产生一个正确的验证URL,实际点击到预期的目的地。 它看起来像这样:

<a href="http://example.com/url?source=web&amp;last=%22f%20o%20o%22&amp;bar=%3C">My Link</a>

最后,对于正确进行URI编码的第三个URL,确实会出现验证的正确HTML。

<a href="https://www.google.com/url?source=web&amp;sqi=2&amp;url=https%3A%2F%2Ftwitter.com%2F%3Flang%3Den&amp;last=%22foo%22">My Link</a>

并且它会执行用户在单击时期望发生的事情。

基于此,算法应该是:

if url is encoded then
 pass as-is to attr()
else
 pass encodeURI(url) to attr()

然而,基于这两个先前的讨论(实际上,参见示例URL 1),“编码”测试似乎无法在肯定的情况下检测到:

如何确定字符串是否已经过URL编码? 如何知道URL是否被解码/编码?

如果我们绕过attr()方法并强制将示例URL 2的HTML转义版本插入到文档结构中,它将如下所示:

<a href="http://example.com/url?source=web&amp;last=&quot;f+o+o&quot;&amp;bar=&lt;">My Link</a>

看似有效的HTML,但HTML5验证器失败,因为它无法使用无效的URL字符。 但是,浏览器似乎并不介意。 不幸的是,如果你的对象的任何其他操作时,浏览器会重新逃避所有的&反正的。

如您所见,这一切都非常令人困惑。 这是我们第一次使用浏览器本身生成HTML,我们不确定我们是否正确使用它。 以前,我们使用模板对服务器端进行了操作,并且只进行了HTML-escape过滤器。

将用户提供的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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM