在ASP.NET/IIS中使用冒号(:)作为URL的一部分

20

我正在ASP.NET MVC中实现自定义控制器,并且希望能够在URL中使用冒号,以便可以标识类/列名及其值,例如:

http://example.com/user:chaiguy

但显然ASP.NET或IIS不允许在URL中使用冒号。 我进行了一些调查,似乎这被认为是一个安全问题,但我使用的是MVC并手动处理所有URL路径(将它们只视为字符串),而不与文件系统关联,因此我非常确定这不适用。

我还听说过实现自定义Http处理程序之类的话题。

非常感谢任何想法或建议。

...

我建议你构建一个web服务。WCF是一个不错的技术,可以很好地托管在IIS中。

我喜欢URLs,并且对于我的需求来说,WCF太复杂了。 我希望它与REST一样与url兼容,但能够做更多事情,而不仅仅是导航层次结构或执行良好的操作。 我对/users/chaiguy有问题,因为它解释了没有层次结构的东西:在我的系统中,“user”是一个类,而不是一个文件夹。 user:chaiguy表示具有“chaiguy”值的user类的实例,它是单个实体,可能具有子实体。 例如:

/user:chaiguy/name

…我想要显示该实体的名称。如果我用您的方法来做这件事,它会像这样:

/users/chaiguy/name

问题在于你如何知道哪个是类,哪个是值? 在我的系统中,它可以被解释为

/users/chaiguy:name

这在我的系统中没有意义。 看到我的意思了吗? 再举一个稍微复杂一点的例子,假设我们想从多个实例中选择用户实体的子项。 因此,用户可能有几个电子邮件地址。 要选择其中一个,我们可以使用:

/user:chaiguy/email:me@here.com/

因此,它实际上是递归的。 它不是文件路径,而更像是XPath(或根据我所知道的内容,可能类似于jQuery)。也就是说,它更像是动态评估的查询选择,而不是硬连线的文件路径。 它在服务器上计算。

毫无疑问,我正在构建的不是典型的网站甚至不是Web服务。


唉,糟糕。我想我可以很容易地使用URL参数来实现这个功能,例如 ?user=chaiguy,但是路径段中是否支持参数,比如 "/?user=chaiguy/address"? - devios1
如果使用查询参数,您将失去 ASP.NET MVC 的最大好处之一:RESTful URL。 - Randolpho
REST不支持查询参数吗?我以为REST只是基于URL的交互。为什么查询参数不算呢? - devios1
3
我发现维基百科在路径段中使用了冒号,比如2001: A Space Odyssey,这也让我产生了同样的问题。维基百科是全球排名第三的网站,这是不是说明冒号用在网址中是可以的呢?此外,在Firefox浏览器中,如果你复制这个地址,括号会被编码,但冒号不会。但是,如果你调用encodeURIComponent(':')函数,它会返回"%3A",这就是我的检验方法。所以说,冒号不能再被用在网址中了(真遗憾,我还想用它)。 - harpo
5
事实上,维基百科在许多地方都使用冒号,即使在没有明显好处的非常重要的位置,比如他们的“联系我们”页面。你不禁会想,如果这样做是如此危险,他们是如何得以逃脱的?当然,我知道维基百科不使用.NET,但问题(至少对我来说)实际上是围绕着冒号是否是 URL 中合法的字符,与平台无关。 - harpo
显示剩余6条评论
8个回答

20

在web.config中更改httpRuntimerequestPathInvalidCharacters属性:

<httpRuntime maxRequestLength="20480" requestValidationMode="2.0" requestPathInvalidCharacters="" maxQueryStringLength="20480" />

ASP.NET现在不应该阻止请求路径中的冒号了。


2
这个安全吗?我们只想删除冒号,而不是其他字符吗? - Karlas
1
即使使用requestValidationMode="2.0",这也无法在ASP.Net 4中工作。 - Badgerspot
这应该放在 configuration > system.web > httpRuntime 中。 - androbin

4

在这里回答了类似的问题:https://dev59.com/3WLVa4cB1Zd3GeqPwnYO#12037000

看起来 ASP.net 不允许在 URL 的问号之前添加冒号,即使它被编码为 %3A。

例如,以下内容都不起作用:

http://foo.org/api/persons/foo:bar

http://foo.org/api/persons/foo%3abar

但是这个可以:

http://foo.org/api/persons?id=foo%3abar

在所有的例子中,我们都期望 ASP.NET MVC 将“foo:bar”作为一个 id 参数正确解码传递。我刚刚在 MVC4 中测试了一下,它似乎可以工作。虽然它不接受问号之前的 URL 编码,但我相信这其中有一个很好的原因。可能是为了使问号之前的所有内容都是 URL 的有效部分,而问号之后则是任何参数。


1
实际上,http://foo.org/api/persons?id=foo:abar 也可以正常工作 - 不需要转义冒号。 - Evgeniy Berezovsky
就像我之前所说的,这个规则似乎只适用于路径,也就是问号左侧的所有内容。冒号可以出现在问号右侧。 - angularsen

1

尝试设置HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters\AllowRestrictedChars。这来自于http://support.microsoft.com/?id=820129。我不知道ASP.NET/MVC是否会自行进行一些检查,但如果只是http.sys阻止您,那么这应该可以解决问题。


冒号在URL的那个位置是否有效?如果无效,则不要这样做,因为http.sys不是唯一不喜欢它的软件。 - John Saunders

1
我建议你重新考虑你想要做的事情。使用路径来指示上下文并隐藏你的类和字段名称,将特定上下文映射到URL路径中的类名和字段。例如,如果你需要表示一个用户,可以构建你的URL布局为example.com/users/chaiguy而不是example.com/user:chaiguy

4
我知道那是一个选项并感谢你的建议,但我真的很想按照这种方式做。如果我不能使用冒号,我可能会使用其他符号,但冒号会是最理想的。 - devios1
因为我想做的事情非常不同,涉及到与非网络系统的基于URL的交互。 - devios1
我建议你考虑建立一个 Web 服务。WCF 是一个很好的技术,可以很好地托管在 IIS 上。 - Randolpho

1
这个 web.config 设置对我很有效。它接受 URL 中的冒号(:)。
<httpRuntime targetFramework="4.6.1" requestPathInvalidCharacters=""/>

0

实际上,有WCF REST可用,您可以使用此处提供的WCF Starter Kit在一小时内轻松启动。它将REST的强大功能与WCF的易用性相结合。此外,使用WCF,您还可以创建自己的传输层,如果需要,可以以任何希望的方式解释URL。关于起始套件的一个有趣之处是它允许Url中包含空格,这实际上给真正的REST基金会带来了一些麻烦。

由于WCF,我不太想看它,但实际上您并不需要了解那么多。该解决方案会为您创建所需的一切,只需添加代码即可。


1
难道你不是想说WCF的强大和REST的简便性吗? ;) - devios1

-4
我建议使用句号。REST是基于HTTP协议的一个例子,它构建了一个新的HTTP用法,并遵循标准,取得了巨大成功。也许你可以这样做。
在许多语言中,'.'是一个标准的'class.method'或'class.attribute'。
现在,我想在时间URL参数中使用冒号,在一些地方已经有人这样做了。我还需要看看是否能够成功。
对我来说,我可能会使用这个: http://www.businesscasualblog.com/2009/07/how-to-share-a-link-to-a-specific-timecode-in-youtube-video.html 基本上是 '--h--m--s'。

-10

URL中可以使用冒号吗?简短回答不行

长话短说,如果它在URL的片段中,则可以。

例如:http://site/gwturl#user:45/comments(请注意,冒号在井号之前)

来源

  • 这个答案,
  • Is a colon safe for friendly-URL use?
  • 以及通过在ASP.NET中将:添加到URL并获得YSOD的个人测试,其中包含A potentially dangerous Request.Path value was detected from the client (:)

2
冒号在URL中是有效的。请检查RFC 2396的语法,该语法被HTTP 1.1规范所引用,或者较新的RFC 3986的语法。您会发现冒号在路径和查询中也是有效的。 - Evgeniy Berezovsky
@meh EugeneBeresovksy,我支持我的答案,特别是最后一点。 - Chris Marisic
关于你最后提到的问题,OP已经意识到了这个问题,这也是他为什么会问的原因。我提供了相关的RFC链接,证明冒号是有效的。实际上,可能是片段中的冒号会有问题(取决于使用的HTML版本)。尽管如此,各种HTTP和HTML规范有时会存在冲突,但总体而言,冒号是有效的。至于asp.net不喜欢它们并试图提供一些伪安全性(可以使用“requestPathInvalidCharacters”标志关闭),那是另一回事。 - Evgeniy Berezovsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接