Ssrs

ReportManager 如何在外部使用與防火牆後面不同的埠?

  • December 15, 2013

我在本機模式下使用 SSRS 2012。配置似乎與我升級的 SSRS 2008 相比沒有太大變化,因此該問題適用於兩個版本(但是,如果有解決方案,它可能適用於也可能不適用於兩個版本)。

我的情況是,我想從防火牆外部的一組埠提供 ReportManager 網站,但在內部,在不同的埠上設置了 SSRS。有誰知道如何做到這一點?

細節

這是一個問題的原因是因為 SSRS 程式碼堅持建構到 ReportManager 網站內不同位置的完整、絕對 URL。(IMO,這只是 SSRS 中許多重大/嚴重的設計缺陷之一)如果它只使用沒有嘗試指定域+埠的 URL,這不會是一個問題。

例子

讓我們從“ http://reports.example.com/ssrs ”的外部 URL 開始,並且 ReportManager 被配置為使用埠 8080(當然,您的埠轉發從埠 80 到 8088)。如果您訪問外部 URL,您會很好地訪問該站點;讓我們忽略 AuthC 子系統並假設您登錄正常。對於某些連結(例如“詳細資訊視圖”、“移動”、“刪除”等),現在您不會去您預期的地方,因為 SSRS 會嘗試將您發送到“ http://reports.example”。 com:8080/ssrs/ …"。您可以通過刪除埠手動修復連結,然後您將進入該頁面。SSRS 2012 和 SSRS 2008 之間破壞的 URL 存在差異,但問題仍然存在。

我有一些適用於 SSRS 2012 的東西,但它完全是 hack。可以使用客戶端 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);
           }
       }
   }
}

引用自:https://serverfault.com/questions/515589