确定是绝对 URL 还是相对 URL

Posted

技术标签:

【中文标题】确定是绝对 URL 还是相对 URL【英文标题】:Determine if Absolute or Relative URL 【发布时间】:2011-04-29 11:55:37 【问题描述】:

我在字符串中有一个相对或绝对 url。我首先需要知道它是绝对的还是相对的。我该怎么做呢?然后我想确定 url 的域是否在允许列表中。

这是我的允许列表,例如:

string[] Allowed =

   "google.com",
   "yahoo.com",
   "espn.com"

一旦我知道它是相对的还是绝对的,我认为它相当简单:

if (Url.IsAbsolute)

    if (!Url.Contains("://"))
        Url = "http://" + Url;

    return Allowed.Contains(new Uri(Url).Host);

else //Is Relative

    return true;

【问题讨论】:

别忘了有些人使用www 子域。 与***.com/questions/2201171/…重复 【参考方案1】:
bool IsAbsoluteUrl(string url)

    Uri result;
    return Uri.TryCreate(url, UriKind.Absolute, out result);

【讨论】:

您可以使用Uri.TryCreate 方法来代替更漂亮的代码。 System.Uri 仅在存在方案 (http/https/etc) 时才认为它是绝对的,但浏览器(通常是用户代理)将假定与协议相关的方案相同 '//pirate.ru /' 网址。 要继续@yzorg 的评论,您可能还应该确保url 值不以'//' 开头。如果您使用它来检查有效的重定向,您绝对应该这样做。如果有人知道检测协议相关 URL 的更好或更稳健的方法,我会全力以赴。 这从 /dir/example-img.jpg 返回 true。那是相对路径,对吧? @TEK:一个绝对的路径,但是一个相对的URI【参考方案2】:

出于某种原因,一些不错的答案被其所有者删除:

通过@Chamika Sandamal

Uri.IsWellFormedUriString(url, UriKind.Absolute)

Uri.IsWellFormedUriString(url, UriKind.Relative)

UriParser 和通过@Marcelo Cantos 实现的实现

【讨论】:

不幸的是,这会为//www.google.com 生成false,这是一个绝对的uri(您可以重定向到它并且浏览器会访问实际域)。它可能导致严重的安全问题。从上面的答案中检查@JT 评论。 不幸的是,302 在每个浏览器中都以这种方式处理这个问题。如果有人想检查他们是否容易受到 Open Redirect 的攻击并以某种方式在谷歌上搜索“如何检查 url 是否是绝对的”,请到这里并按照提供的答案进行操作,漏洞仍然存在。请考虑此评论不是指出您的答案是错误的(不是),而是作为对寻求稍微不同问题答案的人的警告。包括我自己。 @WiktorZychla 如果您想阻止开放重定向,请测试 maybeUnsafeUri.Host 什么是maybeUnsafeUri.Host var maybeUnsafeUri = new Uri(externalStringUrl) 然后您测试 Host 以确保它是您信任的服务器。【参考方案3】:

您可以使用UriBuilder 更直接地实现您想要的,它可以处理相对和绝对 URI(参见下面的示例)。

@icktoofay 也提出了一个很好的观点:确保在您的允许列表中包含子域(如www.google.com)或对builder.Host 属性进行更多处理以获取实际域。如果您决定进行更多处理,请不要忘记具有复杂 TLD 的 URL,例如 bbc.co.uk

using System;
using System.Linq;
using System.Diagnostics;

namespace UriTest

    class Program
    
        static bool IsAllowed(string uri, string[] allowedHosts)
        
            UriBuilder builder = new UriBuilder(uri);
            return allowedHosts.Contains(builder.Host, StringComparer.OrdinalIgnoreCase);
        

        static void Main(string[] args)
        
            string[] allowedHosts =
            
                "google.com",
                "yahoo.com",
                "espn.com"
            ;

            // All true
            Debug.Assert(
                IsAllowed("google.com", allowedHosts) &&
                IsAllowed("google.com/bar", allowedHosts) &&
                IsAllowed("http://google.com/", allowedHosts) &&
                IsAllowed("http://google.com/foo/bar", allowedHosts) &&
                IsAllowed("http://google.com/foo/page.html?bar=baz", allowedHosts)
            );

            // All false
            Debug.Assert(
                !IsAllowed("foo.com", allowedHosts) &&
                !IsAllowed("foo.com/bar", allowedHosts) &&
                !IsAllowed("http://foo.com/", allowedHosts) &&
                !IsAllowed("http://foo.com/foo/bar", allowedHosts) &&
                !IsAllowed("http://foo.com/foo/page.html?bar=baz", allowedHosts)
            );
        
    

【讨论】:

这适用于相对网址吗? ./page/test.aspx 之类的东西编辑:刚刚测试过,它无法处理相对 url。 uribuilder 有处理相关内容的方法吗? @Mark:不,在这种情况下,UriBuilder 无法知道您想要什么主机。它抛出一个异常。不过,我认为没有任何方法可以处理这种情况,因为这是一个相对于任何内容的 URL(或者至少没有指定)。 @Mark:忽略我的最后一条评论,我看到您只想return true; 用于相关情况,因此您可以按照@Ian 的建议使用Uri.TryCreate 我使用其他代码来确定 url 是绝对的还是相对的,以及包含部分的代码。谢谢。

以上是关于确定是绝对 URL 还是相对 URL的主要内容,如果未能解决你的问题,请参考以下文章

绝对与相对 URL

302 重定向到相对 URL 是有效的还是无效的?

请教一个PHP中相对url和绝对url的问题

302 重定向到相对 URL 是有效的还是无效的?

仅打印绝对 URL

如何确定录制宏将使用绝对引用还是相对引用?