哪些字符使网址无效?

goo*_*ood 486 validation url rfc3986

哪些字符使网址无效?

这些有效的网址是?

  • example.com/file[/].html
  • http://example.com/file[/].html

Gum*_*mbo 568

通常,RFC 3986定义的URI (请参阅第2节:字符)可以包含以下任何字符:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Run Code Online (Sandbox Code Playgroud)

请注意,此列表未说明URI中可能出现这些字符的位置.

任何其他字符都需要使用percent-encoding(%hh)进行编码.URI的每个部分对于需要由百分比编码的单词表示的字符有进一步的限制.

  • 这是一个正则表达式,它将确定整个字符串是否只包含上面的字符:/ ^ [!#$& - ; =? - \[\ _] _ a-z~] + $ / (74认同)
  • @techiferous,是的,我忘了允许"%"转义字符.它应该看起来更像:`/ ^([!#$& - ; =? - [] _ a-z~] |%[0-9a-fA-F] {2})+ $ /`有没有你发现它应该接受的任何其他东西?(为了清楚起见,正则表达式只检查字符串是否包含有效的URL字符,而不是字符串包含格式良好的URL.) (42认同)
  • (当然,字符列表没有说明*uri中可能出现的*) (29认同)
  • @Weeble我的正则表达式包括使用范围的那些字符.之间 ';' 和'?'之间 并且'['你会找到你没看到的所有那些角色. (13认同)
  • @Timwi RFC 3986说:"百分比编码的八位字节被编码为字符三元组,由百分号字符"%"后跟两个十六进制数字组成,后面跟着八位字节的数字值." 它还说,"因为百分比("%")字符用作百分比编码八位字节的指示符,所以必须将百分比编码为"%25",以便将该八位字节用作URI中的数据.我读到这就是说"%"只有在后跟两个十六进制数字时才会出现.你怎么看的? (12认同)
  • @MarkusvonBroady`budyń.pl`是一个所谓的国际域名(IDN),实际上被翻译成[punycode](http://tools.ietf.org/html/rfc5891)`xn--budy-e2a.pl `.当您在浏览器中输入`http://budyń.pl`时,它实际上会请求`http:// xn - budy-e2a.pl`. (4认同)
  • @Gumbo我知道它,但翻译是在幕后完成的; 在创建论坛脚本时,比如问题作者描述的情况,您需要考虑这些不寻常的情况.事实上,我不明白为什么脚本应该检查电子邮件/ URL有效性 - 我看到的大多数regexp比RFC更具限制性,因此导致异国地址出现问题.我只会检查该方案是否在http(s),ftp,磁铁等白名单中,并将标签放在"<>"而不是"[]"中,因为后者也可以在链接内. (4认同)
  • @Leif,正则表达式缺少一些字符,并没有正确地逃避其他人.这个正则表达式应该更好用:/(http[A-Za-z0-9\-\.\_~:\/\?#\[\]@!\$&'\(\)\*.+, =%] +)/ (3认同)
  • `#`标记片段的开头,通过正则表达式允许它是不明智的 (3认同)
  • @Pacerier我的观点是,您要么:1.使用正则表达式查找链接.这样,使用上面的版本,你永远不会找到`http://budyń.pl`链接,所以你永远不会翻译它,它将被解析为纯文本(至少在角色不在regexp公式内部分之后) ).--- 2.使用regexp验证链接.这样,即使它是一个将在浏览器中打开的有效链接,您也不会允许用户键入`http://budyń.pl`.这就是为什么我在这里测试它来支持我的观点,以现实生活为例:: http://budyń.pl/ (3认同)
  • @Pacerier Regex非常强大且有用。使用正确的工具完成工作。排除任何原因是因为有一些发声的程序员过于愚蠢或懒惰而无法掌握一些非常强大的工具,这是不必要地且不善地重塑某些现有解决方案的一种方法。 (3认同)
  • @Eamon Nerbonne:是的,这只是所有组件的有效字符集的联合。 (2认同)
  • @techiferous你的正则表达式没有逃脱字符类中的结束方括号"]".我想你的意思是/(http[A-Za-z0-9\-\._~::/\?#[\\]@!\$&'()*,+,,==%++)/编辑 - (啊哈,StackOverflow删除了它.你需要包含两个才能显示.我不确定它是否也可以吃掉其他字符......) (2认同)
  • “ http://budyń.pl”是一个地址示例,该地址的字符超出了给定的有效字符范围。地址有效。有趣的是,它在SO中的解析不是正确的:http://budyń.pl我认为您在解析URL时应该放任自流(`http://`前缀字符串是显而易见的链接),而在页面中却非常严格命名,URL重写等 (2认同)

Jas*_*nM1 183

为了添加一些说明并直接解决上面的问题,有几类字符会导致URL和URI出现问题.

有些字符是不允许的,不应出现在URL/URI,保留字符(如下所述)中,以及在某些情况下可能导致问题的其他字符,但标记为"不明智"或"不安全".RFC-1738(URL)和RFC-2396(URI)中明确说明了字符受限制的原因.请注意,较新的RFC-3986(对RFC-1738的更新)定义了在给定上下文中允许使用哪些字符的构造,但较旧的规范提供了对以下规则不允许哪些字符的更简单和更一般的描述.

URI语法中不允许排除的US-ASCII字符:

   control     = <US-ASCII coded characters 00-1F and 7F hexadecimal>
   space       = <US-ASCII coded character 20 hexadecimal>
   delims      = "<" | ">" | "#" | "%" | <">
Run Code Online (Sandbox Code Playgroud)

允许列出不明智的字符,但可能会导致问题:

   unwise      = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Run Code Online (Sandbox Code Playgroud)

在查询组件中保留的字符和/或在URI/URL中具有特殊含义:

  reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Run Code Online (Sandbox Code Playgroud)

上面的"保留"语法类指的是URI中允许的那些字符,但在通用URI语法的特定组件中可能不允许这些字符."保留"集中的字符不会在所有上下文中保留.例如,主机名可以包含可选的用户名,因此它可能类似于ftp://user@hostname/'@'字符具有特殊含义的地方.

以下是包含无效和不明智字符的网址示例(例如'$','[',']'),并且应正确编码:

http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Run Code Online (Sandbox Code Playgroud)

URI/URL的一些字符限制是依赖于编程语言的.例如,'|' (0x7C)字符虽然在URI规范中仅标记为"不明智",但会在Java java.net.URI构造函数中抛出URISyntaxException,因此不允许使用URL,而必须编码,就像使用带有URI对象实例的Java一样.http://api.google.com/q?exp=a|bhttp://api.google.com/q?exp=a%7Cb

  • 优秀,彻底的答案,唯一一个直接回答实际问题的人.保留部分可能需要工作,例如文字`?`在查询部分中很好*但在它之前是不可能的,我不认为`@`属于这些列表中的任何一个.哦,而不是最后一个字符串中的'%25`,你的意思是'%7C`吗? (2认同)
  • 这个答案并不“糟糕”,但存在一些混乱和错误。您最初将不允许的字符和保留的字符(非常不同的事情)混为一谈,您对“不明智”字符和其他不允许的字符(在 RFC 3986 中被删除,甚至在 RFC 2396 中在语法上不相关)之间做了太多区分,并且您令人困惑地呈现了一个列表所有保留字符作为保留列表*“在查询组件内”*。 (2认同)

Mar*_*ery 79

这里的大多数现有答案都是不切实际的,因为它们完全忽略了地址的实际使用情况,例如:

好的,所以根据RFC 3986,这样的地址不是URI(因此不是URL,因为URL 是一种URI).如果我们认为自己受惠于现有的IETF标准的术语,那么我们应该正确地调用它们的IRI(国际化资源标识符),如定义RFC 3987,这在技术上不是URI的,但可以通过简单地转换为URI的百分之编码所有非-IRI中的-ASCII字符.正常的人,但是,从来没有听说过虹膜和简单地调用这些URI或URL(实际上有一个WHATWG的努力正在创造一个新的,更广阔的URL规范,简单地分类所有"的URI"和"IRIS"的"网址"对齐在现实世界中现代使用这些术语).

假设我们想立即采用URL的这个含义(这与IETF规范不一致,但是我们将其与日常用法联系起来).在这种情况下,哪些字符在URL中有效?

首先,我们有两种类型的RFC 3986 保留字符:

  • %,这是RFC 3986中定义的URI的通用语法的一部分
  • %,它们不是RFC的通用语法的一部分,但保留用作特定URI方案的语法组件.例如,分号和逗号被用作的语法的一部分的数据的URI,并[]被用作普遍存在的一部分:/?#[]@在查询字符串格式(其由RFC 3986规定).

上面的任何保留字符都可以在没有编码的URI中合法使用,既可以用于语法目的,也可以作为数据中的文字字符,在某些地方,这些使用不能被误解为服务于其语法目的的字符.(例如,虽然!$&'()*+,;=在URL中具有语法含义,但您可以在查询字符串中使用未编码的,因为它在查询字符串中没有意义.)

RFC 3986还指定了一些未保留的字符,这些字符总是可以简单地用于表示没有任何编码的数据:

  • &

最后,=允许字符本身进行百分比编码.

只留下以下禁止出现在URL中的ASCII字符:

  • 控制字符(字符0-1F和7F),包括换行,制表符和回车符.
  • ?foo=bar&qux=baz

ASCII中的每个其他字符都可以合法地显示在URL中.

然后RFC 3987使用以下unicode字符范围扩展该组未保留字符:

  %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
/ %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
/ %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
/ %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
/ %xD0000-DFFFD / %xE1000-EFFFD
Run Code Online (Sandbox Code Playgroud)

但鉴于最新的Unicode 块定义,这些块选择看起来很奇怪和随意; 这可能是因为在编写RFC 3987之后的十年中已经添加了块.WhatWG正在进行的规范有一个更慷慨的列表:

U + 00A0到U + D7FF,U + E000到U + FDCF,U + FDF​​0到U + FFFD,U + 10000到U + 1FFFD,U + 20000到U + 2FFFD,U + 30000到U + 3FFFD,U + 40000到U + 4FFFD,U + 50000到U + 5FFFD,U + 60000到U + 6FFFD,U + 70000到U + 7FFFD,U + 80000到U + 8FFFD,U + 90000到U + 9FFFD,U + A0000至U + AFFFD,U + B0000到U + BFFFD,U + C0000到U + CFFFD,U + D0000到U + DFFFD,U + E0000到U + EFFFD,U + F0000到U + FFFFD,U + 100000到U + 10FFFD

当然,应该注意的是,仅仅知道哪些字符可以合法地出现在URL中不足以识别某些给定字符串是否是合法URL,因为某些字符仅在URL的特定部分中是合法的.例如,保留字符/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~是合法的,因为在像URL的IPv6文字主机的一部分的http:// [1080 :: 8:800:200℃:417A] /富但不合法的任何其他上下文中,所以OP的例子%是非法的.

  • plusone 提供详尽的参考资料(例如 RFC) (5认同)
  • +1 表示实际回答问题,而不是解释问题并回答另一个问题。来自 Google,我一直在寻找一些可以用来测试 URL 验证方法的“无效”字符。其他人正在回答如何编写 URL 验证方法...... (4认同)

Dom*_*ers 19

在您的补充问题中,您询问是否www.example.com/file[/].html是有效的URL.

该URL无效,因为URL是一种URI,有效的URI必须具有类似的方案http:(参见RFC 3986).

如果您打算询问是否http://www.example.com/file[/].html是有效的URL,则答案仍然是否定的,因为方括号字符在那里无效.

方括号字符是为此格式的URL保留的:( http://[2001:db8:85a3::8a2e:370:7334]/foo/bar即IPv6文字而不是主机名)

如果你想完全理解这个问题,那么值得仔细阅读RFC 3986.


Cra*_*gTP 11

可以在URI中使用的所有有效字符(URL是一种URI)在RFC 3986中定义.

所有其他字符都可以在URL中使用,前提是它们首先是"URL编码".这涉及更改特定"代码"的无效字符(通常以百分号(%)后跟十六进制数字的形式).

此链接HTML URL编码参考包含无效字符的编码列表.


Cir*_*四事件 9

一些Unicode字符范围是有效的HTML5,尽管使用它们可能仍然不是一个好主意.

例如,href文档说http://www.w3.org/TR/html5/links.html#attr-hyperlink-href:

a和area元素上的href属性必须具有可能由空格包围的有效URL的值.

然后,"有效网址"的定义指向http://url.spec.whatwg.org/,该网站的目的是:

将RFC 3986和RFC 3987与当代实现保持一致,并在此过程中废弃它们.

该文档将URL代码点定义为:

ASCII字母数字,"!","$","&","'","(",")","*","+",","," - ",".","/" ,":",";","=","?","@","_","〜"和代码点的范围为U + 00A0至U + D7FF,U + E000至U + FDCF ,U + FDF​​0至U + FFFD,U + 10000至U + 1FFFD,U + 20000至U + 2FFFD,U + 30000至U + 3FFFD,U + 40000至U + 4FFFD,U + 50000至U + 5FFFD,U +60000到U + 6FFFD,U + 70000到U + 7FFFD,U + 80000到U + 8FFFD,U + 90000到U + 9FFFD,U + A0000到U + AFFFD,U + B0000到U + BFFFD,U + C0000到U + CFFFD,U + D0000到U + DFFFD,U + E1000到U + EFFFD,U + F0000到U + FFFFD,U + 100000到U + 10FFFD.

然后在语句中使用术语"URL代码点":

如果c不是URL代码点而不是"%",则解析错误.

在解析算法的几个部分,包括模式,权限,相对路径,查询和片段状态:所以基本上是整个URL.

此外,验证器http://validator.w3.org/传递的URL类似于"??",并且不传递具有空格等字符的URL"a b"

当然,正如Stephen C所提到的,它不仅仅是关于角色,还关系到背景:你必须要理解整个算法.但是由于类"URL代码点"用于算法的关键点,它可以很好地了解您可以使用或不使用的内容.

另请参见:URL中的Unicode字符


Bun*_*nyk 5

我需要选择字符来分割字符串中的URL,所以我决定创建自己无法在URL中找到的字符列表:

>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Run Code Online (Sandbox Code Playgroud)

因此,可能的选择是换行符,制表符,空格,反斜杠和"<>{}^|.我想我会选择空格或换行符.:)


Chr*_*isR 2

这并不是您问题的真正答案,但验证 URL 确实是一个严重的问题。您可能最好验证域名并保留 URL 的查询部分。这是我的经验。

您还可以对 URL 进行 ping 操作,看看是否会产生有效的响应,但这对于这样一个简单的任务来说可能太过了。

检测 URL 的正则表达式很丰富,google 一下:)