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

标签 javascript html url

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

对于未知最终用户输入的以下 URL,应该将什么呈现到 HTML 中:

  1. http://example.com/?file=some_19%affordable.txt
  2. http://example.com/url?source=web&last="f o o"&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()生成通过 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=&gt;');
 $('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&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 转义.然而,这导致每个 &成为&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,该 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):

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&amp;last=&quot;f+o+o&quot;&amp;bar=&lt;">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/

相关文章:

javascript - 从移动网站链接到亚马逊应用程序中的特定产品

node.js - Express.js 带特殊字符的参数 URL 编码

java - 如何应用onClick函数打开它的URL

javascript - 每次更新 Angular View 时如何停止页面滚动

javascript - 互联网机器人 - 填写表格

javascript - jQuery 包装语法

html - 如何在 VIM 中注释掉 HTML/XML 元素?

javascript - 当它们进入视口(viewport)时加载 div、图像和/或脚本

javascript - 如何使用 data-dismiss 关闭 Bootstrap 面板?

javascript - 在 Bootstrap 上创建一个滑动行