细节

细节

我在本机模式下使用 SSRS 2012。配置似乎与我升级的 SSRS 2008 相比没有太大变化,因此该问题适用于两个版本(但是,如果有解决方案,它可能适用于或不适用于两者)。

我的情况是,我想从防火墙外部的一组端口提供 ReportManager 网站,但在内部,SSRS 安装在不同的端口上。有人知道如何实现吗?

细节

之所以会出现这个问题,是因为 SSRS 代码坚持要构建指向 ReportManager 网站内不同位置的完整、绝对 URL。(在我看来,这只是 SSRS 中许多重大/严重的设计缺陷之一)如果它只使用不尝试指定域+端口的 URL,那么这将不是问题。

例子

让我们从“http://reports.example.com/ssrs“,并且 ReportManager 配置为在端口 8080 上运行(当然,您的端口转发从端口 80 转到 8088)。如果您转到外部 URL,您将顺利访问该网站;让我们忽略 AuthC 子系统并假设您已成功登录。对于某些链接(例如“详细信息视图”、“移动”、“删除”等),现在,您不会到达您预期的位置,因为 SSRS 会尝试将您发送到“http://reports.example.com:8080/ssrs/......”。您可以通过删除端口来手动修复链接,然后您将进入该页面。SSRS 2012 和 SSRS 2008 之间损坏的 URL 有所不同,但问题仍然存在。

答案1

我有一些适用于 SSRS 2012 的方法,但这完全是黑客行为。可以使用客户端 Javascript 重写所有 URL(加上 SSRS 喜欢的偶尔使用的 RedirectUrl 参数),但这不能解释服务器端的 Response.Redirect() 调用。因此,您只能得到部分解决方案。

简而言之,向 ReportManager 添加一个 HttpModule,以便您可以添加 PreRequestHandlerExecute 事件处理程序。在其中,使用 Reflection 修复 GlobalApp.BaseUrl 和 Request.Url,使其脱离 HOST 标头而不是默认标头。您必须更改两者,因为 SSRS 在构建链接时并不总是使用自己的 BaseUrl。(我使用 ILSpy 来查找要更改的字段。)

这是我做的。我确信可以做得更好,但我现在做的已经够好了,我不再关心了。在 SSRS 上工作会耗尽你的求生意志。

编辑:修复了修改 Request.Url 的部分。请注意,虽然它指定了 .Fragment,但客户端不会发送它,因此它始终为空白。

void context_PreRequestHandlerExecute(object sender, EventArgs ea)
{
    HttpApplication app = sender as HttpApplication; // also at: HttpContext.Current.ApplicationInstance
    string host = app.Context.Request.Headers["HOST"];
    if (!string.IsNullOrEmpty(host))
    {
        System.Reflection.FieldInfo fi = typeof(Microsoft.ReportingServices.UI.GlobalApp).GetField("m_baseUrl", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        if (fi != null)
        {
            string protocol = "http://";
            if (app.Context.Request.IsSecureConnection)
                protocol = "https://";
            Uri url = new Uri(string.Format("{0}{1}{2}", protocol, host, app.Context.Request.ApplicationPath));
            fi.SetValue(app as Microsoft.ReportingServices.UI.GlobalApp, url);

            fi = typeof(System.Web.HttpRequest).GetField("_url", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            if (fi != null)
            {
                url = new Uri(string.Format("{0}{1}{2}{3}{4}", protocol, host, app.Context.Request.FilePath, app.Context.Request.Url.Query, app.Context.Request.Url.Fragment));
                fi.SetValue(app.Context.Request, url);
            }
        }
    }
}

相关内容