2016-09-30 52 views
4

给定一个URL的Web表单中的任意客户输入,我想在href内生成一个包含该URL的新HTML文档。我的问题是我该如何在HTML中保护该URL。将用户提供的URL数据安全准确地插入HTML5文档的正确方法是什么?

什么应该被渲染到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已经被编码,我认为这是合理的,如果他们从URL栏复制它,然后简单地将它传递给attr()会生成一个有效的URL和文档,该文件通过验证器.w3.org/nu上的Nu HTML检查器。

为了在行动中看到它,我们在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。

两种方式来尝试解决这个问题是给它attr()前)HTML转义的URL。然而,这导致每&成为&amp;attr()实体如&amp;&lt;成为双重逸出,并在文档中的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> 

另一种是URI编码将它传递给attr(),这也导致其实际点击到预定的地点正确的验证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转义版本到文档STRUC TURE,它应该是这样的:

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

这看起来只是有效的HTML,因为它取消转义有无效的URL字符但失败的HTML5验证。但浏览器似乎并不介意。不幸的是,如果你对对象进行任何其他操作,浏览器无论如何都会重新跳过所有的&

正如你所看到的,这一切都很混乱。这是我们第一次使用浏览器来生成HTML,我们不确定我们是否正确。以前,我们使用模板做了服务器端,只做了HTML转义过滤器。

什么是用户提供 URL数据安全,准确地插入到(使用JavaScript)的HTML5文件的正确方法?

回答

0

如果你能承担的网址可能是编码或编码不,你可以沿着这个东西线脱身。尝试解码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> 
+0

谢谢您的回答。我不想有解码的URI。见例#3。如果我解码,然后将它传递给'attr()'方法,我得到双引号的问题。 '%22'在解码时变成''',然后'attr()'将它们转换成'"'。至少浏览器处理其余部分就好了。我认为,如果它解码安全,我知道将原文传递给'attr()'是安全的,否则我必须采取补救措施来保护自己。 – vick

相关问题