确定是绝对 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的主要内容,如果未能解决你的问题,请参考以下文章