【问题标题】:C# Uri with underscore带下划线的 C# Uri
【发布时间】:2020-11-13 16:01:33
【问题描述】:

谁能解释为什么我在 C# (.NET Framework 4.8) 中得到下一个结果:

  • Uri.TryCreate("_g._google._com", UriKind.RelativeOrAbsolute, out _)返回true
  • Uri.TryCreate("http://_g._google._com", UriKind.RelativeOrAbsolute, out _)返回false
  • Uri.TryCreate("http://_g._google.com", UriKind.RelativeOrAbsolute, out _)返回true

更新: 更多案例:

  • Uri.TryCreate("http://_google._com", UriKind.Absolute, out _)返回true
  • Uri.TryCreate("http://_g._google._com", UriKind.Absolute, out _)返回false

【问题讨论】:

  • 您是否抱怨当方案为 http 时,TLD 可能不以下划线开头?

标签: c# uri


【解决方案1】:

URI 提供了一种简单且可扩展的方法来标识资源,它只不过是一个标识符,因此它可以允许一些 URL 不允许的字符,因为它们可以是名称、位置或两者兼而有之。

URLS 是 URI 的子集,受它们可能包含的字符以及这些字符的组织方式限制。如需更多信息,我们可以参考 RFC。

URI 可以进一步分类为定位符、名称或两者。这 术语“统一资源定位器”(URL)是指 URI 的子集 除了识别资源之外,还提供了一种方法 通过描述资源的主要访问机制来定位资源 (例如,它的网络“位置”)。

本质上,所有 URL 都是 URI,但并非所有 URI 都是 URL。 URL 不仅告诉您某物是什么,还告诉您如何访问它。 Daniel Miessler 写了一个good article on the difference of URIs and URLs

因此,您遇到的行为是准确的,因为它不知道您正在尝试创建合法 URL,但不管您正在创建准确的 URI。

为了检测它是否是有效的 URL,请使用 this question 中的以下方法。

public static bool ValidHttpURL(string s, out Uri resultURI)
{
    if (!Regex.IsMatch(s, @"^https?:\/\/", RegexOptions.IgnoreCase))
        s = "http://" + s;

    if (Uri.TryCreate(s, UriKind.Absolute, out resultURI))
        return (resultURI.Scheme == Uri.UriSchemeHttp || 
                resultURI.Scheme == Uri.UriSchemeHttps);

    return false;
}

用法:

string[] inputs = new[] {
                          "https://www.google.com",
                          "http://www.google.com",
                          "www.google.com",
                          "google.com",
                          "javascript:alert('Hack me!')"
                        };
foreach (string s in inputs)
{
    Uri uriResult;
    bool result = ValidHttpURL(s, out uriResult);
    Console.WriteLine(result + "\t" + uriResult?.AbsoluteUri);
}

输出:

True    https://www.google.com/
True    http://www.google.com/
True    http://www.google.com/
True    http://google.com/
False

为什么带有下划线的 URL 从 Uri.TryCreate 返回 false?

使用 Uri.TryCreate 时,包含下划线的 Urls/Uris 将始终返回 false。这是由于modification of the standard

此更改需要以前的所有规则名称 包括下划线字符,改为用破折号重命名。

【讨论】:

  • 所以,我专注于第二种情况,URL 是“_g._google._com”,看起来它是有效的 URL,但无效的 URI。 C# 中有没有办法检查有效的 URL,而不是 URI?
  • 那么,接下来的案例呢? Uri.TryCreate("_google._com", UriKind.Absolute, out _) 返回 true,但 Uri.TryCreate("_g._google._com", UriKind.Absolute, out _) 返回 false?
  • 如果您将方案添加到其中(例如 http 或 https),它应该为带有子域的绝对 URL 返回 true。
  • 我现在看到了这个问题,看起来标准被修改了。我更新了答案,在底部添加了解释。基本上 _google._com 返回 true 的事实似乎是错误的。似乎任何带有下划线的 Uri 都应被视为无效,因为应将下划线替换为破折号。
【解决方案2】:

使用 UriKind.RelativeOrAbsolute,System 将尝试检测传递给它的 URI 字符串的类型是 Ralative 还是 Absolute。如果 Uristring 以“http://”开头,则系统将其检测为绝对 Uri,并且“http://_g._google._com”不是有效的 Uri,因此您得到错误。因此,对于每个选项,它是:

第一种情况:Uri.TryCreate("_g._google._com", UriKind.RelativeOrAbsolute, out _),在此系统中将其视为相对 Url,它是有效的相对 Uri,因此您得到了真实的结果。

第二种情况:Uri.TryCreate("http://_g._google._com", UriKind.RelativeOrAbsolute, out _),因为它以“http://”开头,因此它是绝对的 Uri 但不是有效的,因此您得到错误。

第三种情况:Uri.TryCreate("http://_g._google.com", UriKind.RelativeOrAbsolute, out _),与情况 2 相同,但在这种情况下,它是有效的 Uri,因为它在 .com 之前缺少 _。这样你就得到了一个真实的。

【讨论】:

    猜你喜欢
    • 2013-03-31
    • 2023-03-19
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 2018-01-17
    相关资源
    最近更新 更多