本文將介紹使用 ReportViewer 控制項瀏覽遠端報表時,可能發生【The request failed with HTTP status 401: Unauthorized.】的可能解決方案。
【情境描述】
當您嘗試在 ASP.NET 應用程式中利用 ReportViewer 控制項瀏覽部署在遠端的 SSRS 報表時,可能發生【The request failed with HTTP status 401: Unauthorized.】的錯誤,該如何解決?請見下一節。
【實作步驟】
預設情況下 SSRS 採用 Negotiate 驗證及 NTLM 驗證(Windows 整合模式),若您的 IIS 和 SSRS 分別部署自不同機器上,並嘗試在部署到 IIS 的 ASP.NET 應用程式中使用透過 ReportViewer 控制項存取遠端報表時,由於權限關係可能導致無法正常瀏覽報表,在此筆者提出兩個可能的解決方案,您可以依照您的實際情況選擇適合的作法,若有其他做法也歡迎提出來討論。
首先您可以嘗試於 SSRS 報表管理員中利用新增角色指派的方式指定使用者或群組才可以瀏覽報表,例如下圖的 ReportBrowsers 為一個本機群組,筆者將之設定為目前畫面中這份報表的瀏覽器角色。接著您就可以利用模擬或設定 ReportServerCredentials 的方式,藉由隸屬該本機群組中的成員來觀看報表。
方法一、在 ASP.NET 應用程式中實作模擬(impersonate)
您可以在 web.config 中的利用 identity 標籤來啟用模擬(impersonate),若要模擬特定使用者,可以搭配 userName 和 password 屬性來模擬特定使用者,不過使用這種方法雖然方便,但 Microsoft 並不建議使用,您可以改用程式碼來模擬驗證使用者,詳情可以參考 KB 306518。
<identity impersonate="true" userName="accountname" password="password" />
方法二、設定 ReportServerCredentials
您也可以利用下列的程式碼來建立 ReportServerCredentials。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Security.Principal; using System.Net; using Microsoft.Reporting.WebForms; namespace CTS.Library { class ReportServerCredentials : IReportServerCredentials { private string reportServerUserName; private string reportServerPassword; private string reportServerDomain; public ReportServerCredentials(string userName, string password, string domain) { reportServerUserName = userName; reportServerPassword = password; reportServerDomain = domain; } public WindowsIdentity ImpersonationUser { get { // 使用預設識別. return null; } } public ICredentials NetworkCredentials { get { // 使用預設識別 return new NetworkCredential(reportServerUserName, reportServerPassword, reportServerDomain); } } public void New(string userName, string password, string domain) { reportServerUserName = userName; reportServerPassword = password; reportServerDomain = domain; } } }
接著在使用 ReportViewer.ServerReport.SetParameters 方法指定報表參數前,利用下列程式碼來指定瀏覽報表的使用者帳號及密碼,最後一樣是呼叫 ReportViewer.ServerReport.Refresh 方法即可順利顯示遠端報表。
ReportViewer.ServerReport.ReportServerCredentials = new ReportServerCredentials("accountname", "password", "domain");
【參考資料】
- Setting ReportServerCredentials for ReportViewer
- Understanding SQL Server Reporting Services Authentication