【问题标题】:What are the safe characters for making URLs?制作 URL 的安全字符是什么?
【发布时间】:2010-10-16 06:39:02
【问题描述】:

我正在创建一个包含文章的网站,我需要文章根据标题具有“友好”的 URL。

例如,如果我的文章标题是"Article Test",我希望URL 是http://www.example.com/articles/article_test

但是,文章标题(作为任何字符串)可以包含多个特殊字符,这些字符无法在我的 URL 中按字面意思输入。例如,我知道?# 需要替换,但我不知道所有其他的。

URL 中允许使用哪些字符?什么东西可以安全保存?

【问题讨论】:

  • 有一个类似的问题,here。看看吧,你也可以在那里找到一些有用的答案(有很多)。
  • 我将问题改写为更清楚。问题和答案很有用,而且质量很好。 (包括我在内的 48 人都收藏了)在我看来,它应该重新打开。

标签: url friendly-url


【解决方案1】:

引用RFC 3986的第2.3节:

URI 中允许的字符,但没有保留字符 目的,称为无保留。这些包括大写和小写 字母、十进制数字、连字符、句点、下划线和波浪号。

  ALPHA  DIGIT  "-" / "." / "_" / "~"

请注意,与旧的 RFC 2396 相比,RFC 3986 列出的保留标点符号更少。

【讨论】:

  • @Skip Head,“字符”是否包括拉丁编码字符,如 çõ
  • @Mohamad:不,只有 ASCII,虽然 UTF-8 支持越来越好。
  • @Mohamad:最后一部分将在后台更改为post-title-with-%C3%A7-and-%C3%B5,但仍会在用户的位置栏中显示为post-title-with-ç-and-õ
  • 您的读者是葡萄牙语,所以请使用葡萄牙语字符。
  • 因为引用的文件很老,而且这篇文章也是如此。只是想知道这仍然有效还是我们有任何更新的文档。
【解决方案2】:

您需要注意两组字符:reservedunsafe

保留字符是:

  • 和号(“&”)
  • 美元(“$”)
  • 加号(“+”)
  • 逗号 (",")
  • 正斜杠(“/”)
  • 冒号(“:”)
  • 分号(“;”)
  • 等于 ("=")
  • 问号(“?”)
  • 'At' 符号 ("@")
  • 磅(“#”)。

一般认为不安全的字符有:

  • 空格(“”)
  • 小于和大于(“”)
  • 打开和关闭括号(“[]”)
  • 左大括号和右大括号(“{}”)
  • 管道(“|”)
  • 反斜杠(“\”)
  • 插入符号(“^”)
  • 百分比(“%”)

我可能忘记了一个或多个,这导致我回响Carl V's answer。从长远来看,您最好使用允许字符的“白名单”然后对字符串进行编码,而不是试图与服务器和系统不允许的字符保持同步。

【讨论】:

  • # 是用于特定页面上的书签的保留字符,由一个具有匹配名称属性或 id 属性的 HTML 元素创建(无 #-symbol)。跨度>
  • 问号在这里显示为保留和不安全 - 我认为它只是保留,但我可能不正确
  • 其他人似乎不同意波浪号 ~ 不安全。你确定是吗?
  • 如果处理英语以外的语言,白名单就不是很好。 Unicode 只是有太多的 OK 代码点。因此,将不安全的列入黑名单可能是最容易在正则表达式中实现的。
  • 我在这里根据这个答案制作了一个有效的正则表达式:regex101.com/r/9VBu66/1,并附有以下注释。 1. 第一部分将非 ascii 字符列入黑名单,因此如果您想支持 Unicode,则需要将其删除。 2. 我没有将 / 列入黑名单,因为我允许子目录。这是我正在使用的正则表达式:/([^\x00-\x7F]|[&$\+,:;=\?@#\s<>\[\]\{\}|\\\^%])+/
【解决方案3】:

始终安全

从理论上和规范来看,这些基本上在任何地方都是安全的,除了域名。 Percent-encode 任何未列出的内容,一切顺利。

    A-Z a-z 0-9 - . _ ~ ( ) ' ! * : @ , ;

有时安全

只有在特定的 URL 组件中使用时才安全;小心使用。

    Paths:     + & =
    Queries:   ? /
    Fragments: ? / # + & =
    

永远不安全

根据 URI 规范 (RFC 3986),所有其他字符都必须进行百分比编码。这包括:

    <space> <control-characters> <extended-ascii> <unicode>
    % < > [ ] { } | \ ^
    

如果考虑最大兼容性,请将字符集限制为 A-Z a-z 0-9 - _ 。 (句点仅用于文件扩展名)。

牢记上下文

即使根据规范有效,URL 仍然可能是“不安全的”,具体取决于上下文。例如包含无效文件名字符的 file:/// URL,或者在不用作分隔符时包含“?”、“=”和“&”的查询组件。这些情况的正确处理通常取决于您的脚本并且可以解决,但请记住这一点。

【讨论】:

  • 您能否为您的第二次声明(“有时安全”)提供任何来源?特别是,我认为您说= 对查询不安全是错误的。例如,FIQL 接受等号并将自己描述为“URI 友好”和“优化并打算在查询组件中使用”。在我的解释中,RFC 3986 明确允许在查询中使用“=”、“&”、“+”等。
  • @DanielM "?"、"=" 和 "&" 在每个规范的查询中都是有效的,尽管在实践中它们被广泛用于解析查询中的名称-值对。因此,它们作为名称/值本身的一部分可能是不安全的。这是否构成“不安全”可能是一个见仁见智的问题。
  • 一些来源,根据要求。 (1) RFC 3986,第 3.4 节:“[...] 查询组件通常用于以 'key=value' 对 [...] 的形式携带识别信息”(2) WhatWG URL Spec,Sec. 6.2:“构造和字符串化 URLSearchParams 对象非常简单:[...] params.toString() // "key=730d67"” (3) PHP 手册,http-build-query:“生成 URL 编码的查询字符串。[...] 上面的示例将输出:0=foo&amp;1=bar[...]" (4) J. Starr, Perishable Press:“在构建网页时,通常需要添加需要参数化查询字符串的链接。”
  • @Beejor :我正在构建一个 URL,我使用 '-' 和 ';'在施工期间。它不是网络应用程序,而是移动应用程序。不是网络开发人员,因此,如果我在 Path 属性中使用上述两个字符,我会安全吗? docs.microsoft.com/en-us/dotnet/api/…
  • @karsnen 这些是有效的 URL 字符。尽管如果用于引用本地文件系统上的路径,请记住,某些系统不允许文件名中包含某些字符。例如,“file:///path/to/my:file.ext”在 Mac 上无效。
【解决方案4】:

您最好只保留一些字符(白名单),而不是删除某些字符(黑名单)。

只要正确编码,您可以在技术上允许任何字符。但是,要本着问题的精神回答,您应该只允许以下字符:

  1. 小写字母(将大写转换为小写)
  2. 数字,0 到 9
  3. 破折号 - 或下划线 _
  4. 波浪号 ~

其他一切都有潜在的特殊含义。例如,您可能认为可以使用 +,但可以将其替换为空格。 & 也很危险,尤其是在使用一些重写规则时。

与其他 cmets 一样,请查看标准和规范以获取完整的详细信息。

【讨论】:

  • 我今天发现,对于 URL 安全的 Base64 编码器而言,前导符是一个错误的字符选择,因为在极少数情况下,您的编码数据可能会产生两个连续的点 (". ."),这很重要,因为它引用了父目录。
  • @pohl:这只是一个问题,如果您的 URL 被用作文件路径,无论是在您的代码中,还是您的网络服务器在将请求转发到脚本之前实际上尝试将 URL 映射到文件(不幸的是很常见)。
  • 实际上,在我们的例子中,使用它作为文件路径是可以的,因为在 unix 文件中允许在其名称中包含多个甚至连续的点。对我们来说,问题出现在一个名为 Site Scope 的监控工具中,它有一个错误(可能是一个幼稚的正则表达式),它报告了虚假的错误停机时间。对我们来说,我们被困在旧版本的 Site Scope 上,管理团队拒绝支付升级费用,并且一个非常重要的客户在他们的合同中写入了 Site Scope(不是等效的)。诚然,大多数人不会发现自己处于我的位置。
  • 感谢上帝,有人在没有太多废话的情况下发布了一个列表。至于点 (.) - 正如@pohl 所说,不要使用它!这是 IIS 上的另一个奇怪案例(不知道这是否发生在其他 Web 服务器上):如果它位于 URL 的末尾,您很可能会收到 404 错误(它会尝试搜索 [/pagename] . 页)
  • 你能改写一下“你最好保持”吗?
【解决方案5】:

看看RFC3986 - Uniform Resource Identifier (URI): Generic Syntax,你的问题围绕着URI的path部分。

    foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment
      |   _____________________|__
     / \ /                        \
     urn:example:animal:ferret:nose

引用第 3.3 节,URI segment 的有效字符是 pchar 类型:

pchar = unreserved / pct-encoded / sub-delims / ":" / "@"

分解为:

ALPHA / DIGIT / "-" / "." / "_" / "~"

pct-encoded

"!" / "$" / "&amp;" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

":" / "@"

或者换句话说:您可以使用ASCII table除了/?#[ 和 @ 中的任何(非控制)字符987654337@.

这种理解得到了RFC1738 - Uniform Resource Locators (URL) 的支持。

【讨论】:

  • 这是理论上正确答案的一个很好的例子,当应用于我们实际生活的现实世界时会导致麻烦。确实,这些字符中的大多数不会引起问题时间。但现实世界中存在诸如代理、路由器、网关、中继等之类的东西,所有这些都“喜欢”以无视理论标准的方式检查 URL 并与之交互。为了避免这些陷阱,您几乎只能转义除字母数字、破折号、下划线和句点之外的所有内容。
  • @deltamind106 您能否提供示例和/或参考来阐明根据 RFC 安全的字符中的哪些实际上不是?我更愿意在我的回答中坚持由标准支持的事实,如果你能查明我可能忽略的任何事实,我很乐意更新我的答案。
  • @deltamind106 我建议我们尝试让产品遵循标准,而不是告诉开发人员不要这样做。我认为您的警告值得,但如有必要,我们应该尽自己的一份力量向供应商报告违规行为。
  • @Philzen :我正在构建一个 URL,我使用 '-' 和 ';'在施工期间。它不是网络应用程序,而是移动应用程序。不是网络开发人员,因此,如果我在 Path 属性中使用上述两个字符,我会安全吗? docs.microsoft.com/en-us/dotnet/api/…
  • @karsnen 是的,当然 -; 是安全的,这就是我的回答和 RFC 明确指出的内容。
【解决方案6】:

根据您所描述的上下文,我怀疑您实际上想要制作的是一种称为“SEO slug”的东西。最普遍的已知做法是:

  1. 转换为小写
  2. 将 a-z 和 0-9 以外的整个字符序列转换为一个连字符 (-)(不是下划线)
  3. 从 URL 中删除“停用词”,即“a”、“an”和“the”等无意义的可索引词; Google 的“停用词”可查看大量列表

因此,例如,一篇标题为“The Usage of !@%$* to Represent Swearing In Comics”的文章会得到一个“usage-represent-swearing-comics”。

【讨论】:

  • 从网址中删除这些“停用词”真的是一个好方法吗?搜索引擎会因此惩罚网站吗?
  • 通常认为搜索引擎只承认 URL 的某些部分和/或降低对后面部分的重要性,因此通过删除停用词您正在做的事情是最大化您嵌入的关键字数量在您有机会实际排名的网址中。
  • @chaos 如果您考虑到这一点,您是否仍然建议剥离 StopWord:seobythesea.com/2008/08/google-stopword-patent 另外,您能推荐一个好的停用词列表吗?这是迄今为止我找到的最好的列表 - link-assistant.com/seo-stop-words.html
  • @kape123 这对我来说看起来不是一个很好的列表。 “c”和“d”是编程语言,许多其他词看起来也很重要。我可能只是去掉基本的:a, and, is, on, of, or, the, with。
【解决方案7】:

未保留 = ALPHA / DIGIT / "-" / "." /“_”/“~”

【讨论】:

  • “ALPHA”不是暗示“DIGIT”吗?我假设 ALPHA 是“字母数字”的缩写,字母数字表示大写、小写和数字。
  • 其实 alpha 并不意味着字母数字。字母和数字是两个不同的东西,字母数字是这些东西的组合。他本可以这样写他的答案:ALPHANUMERIC / “-” / “。” /“_”/“~”
  • RFC 3986 中“未保留”的 ABNF 表示法将它们分别列出。
【解决方案8】:

URI 的格式在RFC 3986 中定义。有关详细信息,请参阅第 3.3 节。

【讨论】:

    【解决方案9】:

    从 SEO 的角度来看,连字符比下划线更受欢迎。转换为小写,删除所有撇号,然后用单个连字符替换所有非字母数字字符串。剪掉开头和结尾多余的连字符。

    【讨论】:

    • 为什么连字符优先于下划线?解释是什么?
    • @PeterMortensen studiohawk.com.au/blog/…。或者更好:ecreativeim.com/blog/index.php/2011/03/30/…“Google 将连字符视为单词分隔符,但不会以这种方式处理下划线。Google 将和下划线视为单词连接器 - 因此 red_sneakers 与 Google 的 redsneakers 相同”
    【解决方案10】:

    我遇到了类似的问题。我希望有漂亮的 URL,并得出结论,我必须在 URL 中只允许字母、数字和 - 和 _。

    那很好,但后来我写了一些不错的正则表达式,我意识到它可以识别所有 UTF-8 字符都不是 .NET 中的字母并且被搞砸了。这似乎是 .NET 正则表达式引擎的一个已知问题。所以我得到了这个解决方案:

    private static string GetTitleForUrlDisplay(string title)
    {
        if (!string.IsNullOrEmpty(title))
        {
            return Regex.Replace(Regex.Replace(title, @"[^A-Za-z0-9_-]", new MatchEvaluator(CharacterTester)).Replace(' ', '-').TrimStart('-').TrimEnd('-'), "[-]+", "-").ToLower();
        }
        return string.Empty;
    }
    
    
    /// <summary>
    /// All characters that do not match the patter, will get to this method, i.e. useful for Unicode characters, because
    /// .NET implementation of regex do not handle Unicode characters. So we use char.IsLetterOrDigit() which works nicely and we
    /// return what we approve and return - for everything else.
    /// </summary>
    /// <param name="m"></param>
    /// <returns></returns>
    private static string CharacterTester(Match m)
    {
        string x = m.ToString();
        if (x.Length > 0 && char.IsLetterOrDigit(x[0]))
        {
            return x.ToLower();
        }
        else
        {
            return "-";
        }
    }
    

    【讨论】:

    【解决方案11】:

    当我通过 Ajax/PHP 将一个值返回到一个 URL 时,我发现将我的 URL 编码为一个安全的 URL 非常有用,然后页面再次读取该 URL。

    带有特殊字符 &amp; 的 URL 编码器的 PHP 输出:

    // PHP returning the success information of an Ajax request
    echo "".str_replace('&', '%26', $_POST['name']) . " category was changed";
    
    // JavaScript sending the value to the URL
    window.location.href = 'time.php?return=updated&val=' + msg;
    
    // JavaScript/PHP executing the function printing the value of the URL,
    // now with the text normally lost in space because of the reserved & character.
    
    setTimeout("infoApp('updated','<?php echo $_GET['val'];?>');", 360);
    

    【讨论】:

      【解决方案12】:

      我认为您正在寻找类似“URL encoding”的内容 - 对 URL 进行编码以便在网络上“安全”使用:

      这是一个参考。如果您不想要任何特殊字符,只需删除任何需要 URL 编码的字符:

      HTML URL Encoding Reference

      【讨论】:

        【解决方案13】:

        3-50 个字符之间。可以包含小写字母、数字和特殊字符 - 点 (.)、破折号 (-)、下划线 (_) 和比率 (@)。

        【讨论】:

        • 有任何参考吗?
        猜你喜欢
        • 2011-05-26
        • 1970-01-01
        • 2015-12-12
        • 2011-08-13
        • 1970-01-01
        • 2011-01-09
        • 2011-05-24
        • 1970-01-01
        相关资源
        最近更新 更多