获取没有非标准端口的原始 url (C#)

Posted

技术标签:

【中文标题】获取没有非标准端口的原始 url (C#)【英文标题】:Get original url without non-standard port (C#) 【发布时间】:2011-12-02 06:09:03 【问题描述】:

第一个问题!


环境

MVC、C#、AppHarbor。

问题

我正在调用一个 openid 提供程序,并根据域生成一个绝对回调 url。

在我的本地机器上,如果我点击http://localhost:12345/login,这可以正常工作

Request.Url; //gives me `http://localhost:12345/callback`

但是,在我正在部署的 AppHarbor 上,因为他们使用的是非标准端口,即使我在“http://sub.example.com/login”上点击它

Request.Url; //gives me http://sub.example.com:15232/callback

这搞砸了我的回调,因为端口号不在原始源 URL 中!

我试过了

Request.Url Request.Url.OriginalString Request.RawUrl

全部给我“http://sub.example.com:15232/callback”。

还要澄清这不是领域问题,我从 DotNetOpenAuth 收到的错误消息是

'http://sub.example.com:14107/accounts/openidcallback' not under realm 'http://*.example.com/'. 

我不认为我已经把它塞进去了?

现在,我要考虑一些 hacky 的东西,比如

预处理器命令(#IF DEBUG THEN PUT PORT) 字符串替换(Request.URL.Contains("localhost"))

所有这些都不是 100% 的解决方案,但我厌倦了思考我可能缺少的简单属性。我也读过this,但这似乎没有一个公认的答案(更多的是关于路径而不是权威)。所以我把它放在你们身上。

总结

所以如果我有http://localhost:12345/login,我需要从请求上下文中获取http://localhost:12345/callback

如果我有“http://sub.example.com/login”,我应该得到“http://sub.example.com/callback”,不管它在哪个端口上。

谢谢! (睡觉时间,早上会回答任何问题)

【问题讨论】:

【参考方案1】:

我最初的想法是获取引用变量并检查它是否包含端口,如果是,则使用它,否则不要。

如果这不是一个选项,因为代理可能会删除引荐来源标头变量,那么您可能需要使用一些客户端脚本来获取位置并将其传递回服务器。

我猜测 AppHarbor 使用端口转发到 IIS 服务器,因此即使该站点公开位于端口 80 上,IIS 也将其托管在另一个端口上,因此它无法知道客户端连接的端口。

【讨论】:

我最终使用了 UrlReferrer(由于某种原因,它没有端口 GRR!)但是您的帖子将我引向了那里。我不能立即确定任何后果,但无论如何谢谢:) 您是否尝试使用一些 javascript 来获取端口?您可以在查询字符串中传递它或将其发回。 这很老套,我不想依赖。【参考方案2】:

类似

String port = Request.ServerVariables["SERVER_PORT"] == "80" ? "" : ":" + Request.ServerVariables["SERVER_PORT"];
String virtualRoot = Url.Content("~/");
destinationUrl = String.Format("http://012", Request.ServerVariables["SERVER_NAME"], port + virtualRoot, "/callback");

【讨论】:

这也将删除我的本地主机实例上的端口。 :(【参考方案3】:

这是 AppHarbor 等负载平衡设置中的常见问题 - 我们提供了 example workaround。

更新:对于许多 ASP.NET 应用程序来说,一个更理想的解决方案可能是将aspnet:UseHostHeaderForRequestUrl appSetting 设置为true。我们(AppHarbor)已经看到一些客户在使用 WCF 应用程序时遇到问题,这就是为什么我们没有默认启用它并且仍然针对这些情况推荐上述解决方案。您可以使用 AppHarbor 的“配置变量”对其进行配置,以便在部署时注入 appsettings。更多信息可以在this article找到。

【讨论】:

【参考方案4】:

我最近遇到了一个问题,我将 URL 与当前 URL 进行了比较,然后基于此突出显示导航。它在本地工作,但不能在生产环境中工作。

我将http://example.com/path/to/file.aspx 作为我的文件,但是当查看该文件并运行Request.Url.ToString() 时,它在负载平衡的生产环境中生成了https://example.com:81/path/to/file.aspx

现在我使用Request.Url.AbsolutePath 只给我/path/to/file.aspx,因此忽略了架构、主机名和端口号。

当我需要将它与我使用的每个导航项上的 URL 进行比较时: New Uri(theLink.Href).AbsolutePath

【讨论】:

【参考方案5】:

如果您在框架中使用 UrlBuilder 类,您可以轻松解决这个问题。在构建器类上,如果您将端口设置为 -1,则端口号将被删除:

new UriBuilder("http://sub.example.com:15232/callback") Port = -1

返回:http://sub.example.com/callback

要将端口号保留在本地计算机上,只需检查 Request.IsLocal 并且不要将 -1 应用于端口。

我会将其包装到一个扩展方法中以保持其干净。

【讨论】:

【参考方案6】:

我看到这是一个旧线程。我在 IIS 7.5 上运行 MVC5 时遇到了这个问题,前面有一个 Apache 代理。在服务器之外,我会得到“空响应”,因为 asp.net 应用程序使用自定义端口从 apache 获取 Url。

为了让应用重定向到不包含“自定义”端口的子路径,请忘记 Response/Request 对象,并使用 Transfer 方法。例如,如果我希望用户在尚未登录的情况下自动重定向到登录页面:

if (!User.Identity.IsAuthenticated)   
    Server.TransferRequest("Account/Login");

【讨论】:

以上是关于获取没有非标准端口的原始 url (C#)的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法像在 C++ 中挂钩非托管函数一样在 C# 中挂钩托管函数?

有没有办法像在 C++ 中挂钩非托管函数一样在 C# 中挂钩托管函数?

如何将命令发送到在 perl 的非标准端口上运行的 telnet

从 C# 获取非托管 C++ 函数

如何使用 c# asp.net 从 url 获取数据?

如何获取网站重定向目标网址(最终用户链接)