??? SQL SERVER 2008中,Reporting Service不再依賴于IIS,這帶來很多利處,不過這也意味著不能夠直接通過配置IIS的虛擬目錄部署來實現匿名訪問了。下面我們就看一下在SSRS 2008中怎么能夠實現報表的“匿名訪問”,不過對于一個正式項目來說,
建議不要并且從不允許匿名來訪問報表
。
??? 1. 實現
IReportServerCredentials
接口
??????? 對于使用Asp.Net的ReportViewer控件,實現IReportServerCredentials接口來實現自定義身份驗證,然后通過設置成ReportView的屬性ServerReport.ReportServerCredentials。此接口的定義:
- public ? interface ?IReportServerCredentials ??
- { ??
- ????WindowsIdentity?ImpersonationUser?{? get ;?} ??
- ????ICredentials?NetworkCredentials?{? get ;?} ??
- ???? bool ?GetFormsCredentials( out ?Cookie?authCookie,? out ? string ?userName,? out ? string ?password,? out ? string ?authority); ??
- }??
public interface IReportServerCredentials{ WindowsIdentity ImpersonationUser { get; } ICredentials NetworkCredentials { get; } bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority);}
??????? 此接口定義了三種身份驗證的方式來訪問Report Server,可以單獨使用,也可以組合使用這三種方式。
??????? ImpersonationUser:ReportView在每次WebRequest請求到ReportServer前模擬的一個WindowsIdentity,實際上會調用這個屬性的 WindowsIdentity.Impersonate 方法來完成。如果此屬性返回null的話,則默認使用當前線程用戶。
??????? NetworkCredentials: 此屬性的值將會經由 WebRequest.Credentials 屬性直接傳遞給WebRequest,如果返回null的話,則默認是 CredentialCache.DefaultCredentials ,使用當前上下文的系統憑據,這也是通常我們使用的方式。
??????? GetFormsCredentials:這是ReportServer特有的認證體系,如果返回true的話,輸出參數將用來調用ReportServer上的 LogonUser 方法,這個方法是用來支持服務器上的 安全擴展插件 。
??????? 這個接口是如何被使用的呢,我們從report viewer說起。當ASPX page頁面執行時,ReportView控件并不是一次性的請求ReportServer。這其間其實需要通過ReportViewer HTTP handler多次請求Report Server.就比如報表中顯示一個圖片,在客戶端生成的html中有圖片標簽,對于其中的圖片會請求ReportView控件,ReportView收到請求后會重新請求ReportServer索要這個圖片,ReportServer這時還需要判斷當前請求的用戶是否和初始的用戶一一致,如果一致才會返回圖片。其它的例如ReportView提供的打印,導出也是同樣的原理。
?????? ReportView控件的IReportServerCredentials的實例的屬性,存儲在Asp.net SessionState中,這樣即保證了安全性,又能夠即時的獲取到認證信息。不過這個接口提供的靈活性使我們在設置這個憑據時更加靈活,我們可以如下實現:
??????
- [Serializable] ??
- class ?MyConfigFileCredentials?:?IReportServerCredentials ??
- { ??
- ???? public ?MyConfigFileCredentials() ??
- ????{ ??
- ????} ??
- ? ??
- ???? public ?WindowsIdentity?ImpersonationUser ??
- ????{ ??
- ???????? get ?{? return ? null ;?} ??
- ????} ??
- ? ??
- ???? public ?ICredentials?NetworkCredentials ??
- ????{ ??
- ???????? get ??
- ????????{ ??
- ???????????? return ? new ?NetworkCredential( ??
- ????????????????ConfigurationManager.AppSettings[ "MyUserName" ], ??
- ????????????????ConfigurationManager.AppSettings[ "MyPassword" ]); ??
- ????????} ??
- ????} ??
- ? ??
- ???? public ? bool ?GetFormsCredentials( out ?Cookie?authCookie,? out ? string ?userName,? out ? string ?password,? out ? string ?authority) ??
- ????{ ??
- ????????authCookie?=? null ; ??
- ????????userName?=? null ; ??
- ????????password?=? null ; ??
- ????????authority?=? null ; ??
- ????} ??
- }???
[Serializable]class MyConfigFileCredentials : IReportServerCredentials{ public MyConfigFileCredentials() { } public WindowsIdentity ImpersonationUser { get { return null; } } public ICredentials NetworkCredentials { get { return new NetworkCredential( ConfigurationManager.AppSettings["MyUserName"], ConfigurationManager.AppSettings["MyPassword"]); } } public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority) { authCookie = null; userName = null; password = null; authority = null; }}
??????? 上面我們只提供第二種認證方式,創建一個NetwrokCredential實例,并且采用配置文件中存儲的用戶名和密碼,可以在后期修改。在配置文件中創建兩個參數的值為能夠正常訪問此報表的帳號和密碼,然后給賦值給ReportView的屬性即可:
????????
- ReportViewer1.ServerReport.ReportServerCredentials ?=? new ?MyConfigFileCredentials();??
ReportViewer1.ServerReport.ReportServerCredentials = new MyConfigFileCredentials();
???????? 這樣,當你瀏覽報表程序時,就不會提示輸入用戶名和密碼了。或許你看到這里應該也意識到了,我們所說的匿名訪問報表,并不是說報表設置給了everyone都可以訪問,而是說我們包裝了一下,省略了用戶認證這一步,而模擬成了一個可以訪問的用戶,來實現的“匿名訪問”。其實在先前使用IIS作為報表服務器的時候,也是通過在IIS中設置虛擬目錄或者網站,來實現了這個模擬的動作。
????
?????? 2.實現
IReportServerConnection
接口
????????? 但是如果你的系統中禁止SessionState怎么辦呢。這時你可以考慮實現
IReportServerConnection
或者
IReportServerConnection2
接口:
- public ? interface ?IReportServerConnection?:?IReportServerCredentials ??
- { ??
- ????Uri?ReportServerUrl?{? get ;?} ??
- ???? int ?Timeout?{? get ;?} ??
- } ??
- public ? interface ? class ?IReportServerConnection2?:?IReportServerConnection,?IReportServerCredentials ??
- { ??
- ????IEnumerable<Cookie>?Cookies?{ get ;} ??
- ????IEnumerable< string >?Headers?{ get ;} ??
- }??
public interface IReportServerConnection : IReportServerCredentials{ Uri ReportServerUrl { get; } int Timeout { get; }}public interface class IReportServerConnection2 : IReportServerConnection, IReportServerCredentials{ IEnumerable<Cookie> Cookies {get;} IEnumerable<string> Headers {get;}}
???????? 從這兩個接口的代碼可以看出,他們的實例可以當做IReportServerCredentials來使用,所以上面介紹的方法對于他們們的實現同樣管用。他們的屬性值同樣默認存儲在SessionState中,當SessionState禁止時,我們要提供其它的訪問方式,以下是我們的實現:
???????
- [Serializable] ??
- ?? public ? class ?MyReportServerConnection?:?IReportServerConnection2 ??
- ??{ ??
- ?????? public ?Uri?ReportServerUrl ??
- ??????{ ??
- ?????????? get ??
- ??????????{ ??
- ?????????????? string ?url?=?ConfigurationManager.AppSettings[ "MyReportServerUrl" ]; ??
- ?????????????? if ?( string .IsNullOrEmpty(url)) ??
- ?????????????????? throw ? new ?Exception( "Missing?url?from?the?Web.config?file" ); ??
- ?????????????? return ? new ?Uri(url); ??
- ??????????} ??
- ??????} ??
- ?????? public ? int ?Timeout ??
- ??????{ ??
- ?????????? get ?{? return ?60000;?} ??
- ??????} ??
- ??
- ?????? public ?IEnumerable<Cookie>?Cookies ??
- ??????{ ??
- ?????????? get ?{? return ? null ;?} ??
- ??????} ??
- ?????? public ?IEnumerable< string >?Headers ??
- ??????{ ??
- ?????????? get ?{? return ? null ;?} ??
- ??????} ??
- ??
- ?????? public ?MyReportServerConnection() ??
- ??????{ ??
- ??????} ??
- ??
- ??
- ?????? public ?WindowsIdentity?ImpersonationUser ??
- ??????{ ??
- ?????????? get ?{? return ? null ;?} ??
- ??????} ??
- ??
- ?????? public ?ICredentials?NetworkCredentials ??
- ??????{ ??
- ?????????? get ??
- ??????????{ ??
- ?????????????? string ?userName?=?ConfigurationManager.AppSettings"[myReportViewerUser]; ??
- ?????????????? if ?( string .IsNullOrEmpty(userName)) ??
- ?????????????????? throw ? new ?Exception( "Missing?user?name?from?Web.config?file" ); ??
- ?????????????? string ?password?=?ConfigurationManager.AppSettings[ "MyReportViewerPassword" ]; ??
- ?????????????? if ?( string .IsNullOrEmpty(password)) ??
- ?????????????????? throw ? new ?Exception( "Missing?password?from?Web.config?file" ); ??
- ?????????????? string ?domain?=?ConfigurationManager.AppSettings[ "MyReportViewerDomain" ]; ??
- ?????????????? if ?( string .IsNullOrEmpty(domain)) ??
- ?????????????????? throw ? new ?Exception( "Missing?domain?from?Web.config?file" ); ??
- ?????????????? return ? new ?NetworkCredential(userName,?password,?domain); ??
- ??????????} ??
- ??????} ??
- ??
- ?????? public ? bool ?GetFormsCredentials( out ?Cookie?authCookie, out ? string ?userName, out ? string ?password, out ? string ?authority) ??
- ??????{ ??
- ??????????authCookie?=? null ; ??
- ??????????userName?=? null ; ??
- ??????????password?=? null ; ??
- ??????????authority?=? null ; ??
- ?????????? return ? false ; ??
- ??????} ??
- ??} ??
[Serializable] public class MyReportServerConnection : IReportServerConnection2 { public Uri ReportServerUrl { get { string url = ConfigurationManager.AppSettings["MyReportServerUrl"]; if (string.IsNullOrEmpty(url)) throw new Exception("Missing url from the Web.config file"); return new Uri(url); } } public int Timeout { get { return 60000; } } public IEnumerable<Cookie> Cookies { get { return null; } } public IEnumerable<string> Headers { get { return null; } } public MyReportServerConnection() { } public WindowsIdentity ImpersonationUser { get { return null; } } public ICredentials NetworkCredentials { get { string userName = ConfigurationManager.AppSettings"[myReportViewerUser]; if (string.IsNullOrEmpty(userName)) throw new Exception("Missing user name from Web.config file"); string password = ConfigurationManager.AppSettings["MyReportViewerPassword"]; if (string.IsNullOrEmpty(password)) throw new Exception("Missing password from Web.config file"); string domain = ConfigurationManager.AppSettings["MyReportViewerDomain"]; if (string.IsNullOrEmpty(domain)) throw new Exception("Missing domain from Web.config file"); return new NetworkCredential(userName, password, domain); } } public bool GetFormsCredentials(out Cookie authCookie,out string userName,out string password,out string authority) { authCookie = null; userName = null; password = null; authority = null; return false; } }}
???????? 要使HTTP handler在不存儲的情況下還能夠訪問它,必須還要添加 ReportView的WebConfig配置 :
- <configuration> ??
- ????<appSettings> ??
- ????????<add?key= "ReportViewerServerConnection" ?value= "ReportsPortal.MyReportServerConnection,ReportsPortal" /> ??
- ????</appSettings> ??
- </configuration>??
<configuration> <appSettings> <add key="ReportViewerServerConnection" value="ReportsPortal.MyReportServerConnection,ReportsPortal"/> </appSettings></configuration>
???????? 同樣的,我們直接賦值給ReportView的屬性,就可以實現報表的“匿名訪問”。
??
- this .ReportViewer1.ServerReport.ReportServerCredentials?=?? new ?MyReportServerConnection();??
this.ReportViewer1.ServerReport.ReportServerCredentials = new MyReportServerConnection();
參考和資源:
???? 1.
A Wrapper for Running SQL Server 2008 Reporting Services Reports Anonymously
??? 調用ReportingService2005.asmx服務實現了一個匿名訪問所有報表的管理器。
???? 2.
Custom Credentials in the Report Viewer
? 參考資源,有些為這個文章的譯文
???? 3.
Anonymous access in SQL RS 2008
?? 以另外一種方式來實現的匿名訪問
作者:
孤獨俠客
(
似水流年
)
出處:
http://lonely7345.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
SQL Server BI Step by Step SSRS 2----SQL Server 2008 Reporting Services實現匿名訪問報表
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
