当.NET System.Uri类解析字符串时,它会对输入执行一些规范化操作,例如对方案和主机名进行下限.它还会修剪每个路径段的尾随时段.后一个特性对于OpenID应用程序是致命的,因为一些OpenID(如从Yahoo发布的那些)包括base64编码的路径段,其可以以句点结束.
如何禁用Uri类的周期修剪行为?
使用UriParser.Register初始化的解析器注册我自己的方案GenericUriParserOptions.DontCompressPath可以避免周期修剪,以及其他一些对OpenID也不可取的操作.但我无法为HTTP和HTTPS等现有方案注册新的解析器,我必须为OpenID做这些.
我尝试的另一种方法是注册我自己的新方案,并编程自定义解析器以将方案更改回标准HTTP方案作为解析的一部分:
public class MyUriParser : GenericUriParser
{
private string actualScheme;
public MyUriParser(string actualScheme)
: base(GenericUriParserOptions.DontCompressPath)
{
this.actualScheme = actualScheme.ToLowerInvariant();
}
protected override string GetComponents(Uri uri, UriComponents components, UriFormat format)
{
string result = base.GetComponents(uri, components, format);
// Substitute our actual desired scheme in the string if it's in there.
if ((components & UriComponents.Scheme) != 0)
{
string registeredScheme = base.GetComponents(uri, UriComponents.Scheme, format);
result = this.actualScheme + result.Substring(registeredScheme.Length);
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
UriParser.Register(new MyUriParser("http"), "httpx", 80);
UriParser.Register(new MyUriParser("https"), "httpsx", 443);
Uri z = new Uri("httpsx://me.yahoo.com/b./c.#adf");
var req = (HttpWebRequest)WebRequest.Create(z);
req.GetResponse();
}
}
Run Code Online (Sandbox Code Playgroud)
这实际上几乎可行.该Uri实例报告HTTPS而不是到处httpsx -除了Uri.Scheme财产本身.当您将此Uri实例传递HttpWebRequest给向此地址发送请求时,这是一个问题.显然它会检查Scheme属性并且不会将其识别为"https",因为它只是将明文发送到443端口而不是SSL.
我很高兴任何解决方案:
Uri.Path微软称它将在.NET 4.0中得到修复(尽管从评论中可以看出它尚未修复)
但是,该页面上有一个解决方法.它涉及使用反射来改变选项,因此它可能不符合中等信任要求.只需滚动到底部,然后单击"解决方法"选项卡.
感谢jxdavis和Google的回答:
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/5206beca-071f-485d-a2bd-657d635239c9