SQL Server BI Step by Step SSRS 2----SQL Server 2008 Reporting Services实现匿名访问报表

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:

SQL SERVER 2008中,Reporting Service不再依赖于IIS,这带来很多利处,不过这也意味着不能够直接通过配置IIS的虚拟目录部署来实现匿名访问了。下面我们就看一下在SSRS 2008中怎么能够实现报表的“匿名访问”,不过对于一个正式项目来说,建议不要并且从不允许匿名来访问报表
    1. 实现IReportServerCredentials接口
        对于使用Asp.Net的ReportViewer控件,实现IReportServerCredentials接口来实现自定义身份验证,然后通过设置成ReportView的属性ServerReport.ReportServerCredentials。此接口的定义:

  1. public interface IReportServerCredentials   
  2. {   
  3.     WindowsIdentity ImpersonationUser { get; }   
  4.     ICredentials NetworkCredentials { get; }   
  5.     bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority);   
  6. }  
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中,这样即保证了安全性,又能够即时的获取到认证信息。不过这个接口提供的灵活性使我们在设置这个凭据时更加灵活,我们可以如下实现:
      

  1. [Serializable]   
  2. class MyConfigFileCredentials : IReportServerCredentials   
  3. {   
  4.     public MyConfigFileCredentials()   
  5.     {   
  6.     }   
  7.     
  8.     public WindowsIdentity ImpersonationUser   
  9.     {   
  10.         get { return null; }   
  11.     }   
  12.     
  13.     public ICredentials NetworkCredentials   
  14.     {   
  15.         get  
  16.         {   
  17.             return new NetworkCredential(   
  18.                 ConfigurationManager.AppSettings["MyUserName"],   
  19.                 ConfigurationManager.AppSettings["MyPassword"]);   
  20.         }   
  21.     }   
  22.     
  23.     public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority)   
  24.     {   
  25.         authCookie = null;   
  26.         userName = null;   
  27.         password = null;   
  28.         authority = null;   
  29.     }   
  30. }   
[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的属性即可:
        

  1. ReportViewer1.ServerReport.ReportServerCredentials = new MyConfigFileCredentials();  
  ReportViewer1.ServerReport.ReportServerCredentials = new MyConfigFileCredentials();

         这样,当你浏览报表程序时,就不会提示输入用户名和密码了。或许你看到这里应该也意识到了,我们所说的匿名访问报表,并不是说报表设置给了everyone都可以访问,而是说我们包装了一下,省略了用户认证这一步,而模拟成了一个可以访问的用户,来实现的“匿名访问”。其实在先前使用IIS作为报表服务器的时候,也是通过在IIS中设置虚拟目录或者网站,来实现了这个模拟的动作。

    
       2.实现IReportServerConnection接口
          但是如果你的系统中禁止SessionState怎么办呢。这时你可以考虑实现IReportServerConnection 或者IReportServerConnection2 接口:

  1. public interface IReportServerConnection : IReportServerCredentials   
  2. {   
  3.     Uri ReportServerUrl { get; }   
  4.     int Timeout { get; }   
  5. }   
  6. public interface class IReportServerConnection2 : IReportServerConnection, IReportServerCredentials   
  7. {   
  8.     IEnumerable<Cookie> Cookies {get;}   
  9.     IEnumerable<string> Headers {get;}   
  10. }  
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禁止时,我们要提供其它的访问方式,以下是我们的实现:
       

  1. [Serializable]   
  2.   public class MyReportServerConnection : IReportServerConnection2   
  3.   {   
  4.       public Uri ReportServerUrl   
  5.       {   
  6.           get  
  7.           {   
  8.               string url = ConfigurationManager.AppSettings["MyReportServerUrl"];   
  9.               if (string.IsNullOrEmpty(url))   
  10.                   throw new Exception("Missing url from the Web.config file");   
  11.               return new Uri(url);   
  12.           }   
  13.       }   
  14.       public int Timeout   
  15.       {   
  16.           get { return 60000; }   
  17.       }   
  18.   
  19.       public IEnumerable<Cookie> Cookies   
  20.       {   
  21.           get { return null; }   
  22.       }   
  23.       public IEnumerable<string> Headers   
  24.       {   
  25.           get { return null; }   
  26.       }   
  27.   
  28.       public MyReportServerConnection()   
  29.       {   
  30.       }   
  31.   
  32.   
  33.       public WindowsIdentity ImpersonationUser   
  34.       {   
  35.           get { return null; }   
  36.       }   
  37.   
  38.       public ICredentials NetworkCredentials   
  39.       {   
  40.           get  
  41.           {   
  42.               string userName = ConfigurationManager.AppSettings"[myReportViewerUser];   
  43.               if (string.IsNullOrEmpty(userName))   
  44.                   throw new Exception("Missing user name from Web.config file");   
  45.               string password = ConfigurationManager.AppSettings["MyReportViewerPassword"];   
  46.               if (string.IsNullOrEmpty(password))   
  47.                   throw new Exception("Missing password from Web.config file");   
  48.               string domain = ConfigurationManager.AppSettings["MyReportViewerDomain"];   
  49.               if (string.IsNullOrEmpty(domain))   
  50.                   throw new Exception("Missing domain from Web.config file");   
  51.               return new NetworkCredential(userName, password, domain);   
  52.           }   
  53.       }   
  54.   
  55.       public bool GetFormsCredentials(out Cookie authCookie,out string userName,out string password,out string authority)   
  56.       {   
  57.           authCookie = null;   
  58.           userName = null;   
  59.           password = null;   
  60.           authority = null;   
  61.           return false;   
  62.       }   
  63.   }   
  [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配置:

  1. <configuration>   
  2.     <appSettings>   
  3.         <add key="ReportViewerServerConnection" value="ReportsPortal.MyReportServerConnection,ReportsPortal"/>   
  4.     </appSettings>   
  5. </configuration>  
<configuration>
    <appSettings>
        <add key="ReportViewerServerConnection" value="ReportsPortal.MyReportServerConnection,ReportsPortal"/>
    </appSettings>
</configuration>

         同样的,我们直接赋值给ReportView的属性,就可以实现报表的“匿名访问”。
  
  1. 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

本文转自孤独侠客博客园博客,原文链接:http://www.cnblogs.com/lonely7345/archive/2010/01/10/1643603.html,如需转载请自行联系原作者
相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
5天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
40 10
|
2月前
|
SQL 算法 数据库
【数据库SQL server】关系数据库标准语言SQL之数据查询
【数据库SQL server】关系数据库标准语言SQL之数据查询
95 0
|
2月前
|
SQL 安全 关系型数据库
接上篇文章,在测试宝塔 WAF 的未授权访问漏洞时无意间还发现了一个 SQL 注入漏洞
接上篇文章,在测试宝塔 WAF 的未授权访问漏洞时无意间还发现了一个 SQL 注入漏洞,品相还不错,可执行任意 SQL 语句。 总之,吃了一惊,一个防 SQL 注入的工具居然也有 SQL 注入漏洞。 请看这段代码
408 1
|
5天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
55 6
|
2月前
|
SQL 算法 数据库
【数据库SQL server】关系数据库标准语言SQL之数据更新
【数据库SQL server】关系数据库标准语言SQL之数据更新
33 0
|
2月前
|
SQL 数据库 数据库管理
【数据库SQL server】关系数据库标准语言SQL的基本知识
【数据库SQL server】关系数据库标准语言SQL的基本知识
54 0
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
2月前
|
SQL 算法 数据库
【数据库SQL server】关系数据库标准语言SQL之视图
【数据库SQL server】关系数据库标准语言SQL之视图
72 0
|
2月前
|
SQL 人工智能 算法
【数据库SQL server】传统运算符与专门运算符
【数据库SQL server】传统运算符与专门运算符
68 0
|
15天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
15 0

热门文章

最新文章