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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

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
目录
相关文章
|
25天前
|
SQL 数据库
执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.ConnectionInfo)之解决方案
执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.ConnectionInfo)之解决方案
137 0
|
3月前
|
SQL 运维 监控
SQL Server 运维常用sql语句(二)
SQL Server 运维常用sql语句(二)
31 3
|
3月前
|
SQL XML 运维
SQL Server 运维常用sql语句(三)
SQL Server 运维常用sql语句(三)
20 1
|
3月前
|
Java 测试技术 容器
从零到英雄:Struts 2 最佳实践——你的Web应用开发超级变身指南!
【8月更文挑战第31天】《Struts 2 最佳实践:从设计到部署的全流程指南》深入介绍如何利用 Struts 2 框架从项目设计到部署的全流程。从初始化配置到采用 MVC 设计模式,再到性能优化与测试,本书详细讲解了如何构建高效、稳定的 Web 应用。通过最佳实践和代码示例,帮助读者掌握 Struts 2 的核心功能,并确保应用的安全性和可维护性。无论是在项目初期还是后期运维,本书都是不可或缺的参考指南。
46 0
|
3月前
|
Java 应用服务中间件 Maven
从零到英雄:一步步构建你的首个 JSF 应用程序,揭开 JavaServer Faces 的神秘面纱
【8月更文挑战第31天】JavaServer Faces (JSF) 是一种强大的 Java EE 标准,用于构建企业级 Web 应用。它提供了丰富的组件库和声明式页面描述语言 Facelets,便于开发者快速开发功能完善且易于维护的 Web 应用。本文将指导你从零开始构建一个简单的 JSF 应用,包括环境搭建、依赖配置、Managed Bean 编写及 Facelets 页面设计。
87 0
|
3月前
|
SQL 关系型数据库 MySQL
【超全整理】SQL日期与时间函数大汇总会:MySQL与SQL Server双轨对比教学,助你轻松搞定时间数据处理难题!
【8月更文挑战第31天】本文介绍了在不同SQL数据库系统(如MySQL、SQL Server、Oracle)中常用的日期与时间函数,包括DATE、NOW()、EXTRACT()、DATE_ADD()、TIMESTAMPDIFF()及日期格式化等,并提供了具体示例。通过对比这些函数在各系统中的使用方法,帮助开发者更高效地处理日期时间数据,满足多种应用场景需求。
246 0
|
3月前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
273 0
|
2月前
|
SQL 数据库
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例
SQL Server附加数据库出现错误823,附加数据库失败。数据库没有备份,无法通过备份恢复数据库。 SQL Server数据库出现823错误的可能原因有:数据库物理页面损坏、数据库物理页面校验值损坏导致无法识别该页面、断电或者文件系统问题导致页面丢失。
97 12
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例
|
5天前
|
存储 数据挖掘 数据库
数据库数据恢复—SQLserver数据库ndf文件大小变为0KB的数据恢复案例
一个运行在存储上的SQLServer数据库,有1000多个文件,大小几十TB。数据库每10天生成一个NDF文件,每个NDF几百GB大小。数据库包含两个LDF文件。 存储损坏,数据库不可用。管理员试图恢复数据库,发现有数个ndf文件大小变为0KB。 虽然NDF文件大小变为0KB,但是NDF文件在磁盘上还可能存在。可以尝试通过扫描&拼接数据库碎片来恢复NDF文件,然后修复数据库。
|
2月前
|
SQL 关系型数据库 MySQL
创建包含MySQL和SQLServer数据库所有字段类型的表的方法
创建一个既包含MySQL又包含SQL Server所有字段类型的表是一个复杂的任务,需要仔细地比较和转换数据类型。通过上述方法,可以在两个数据库系统之间建立起相互兼容的数据结构,为数据迁移和同步提供便利。这一过程不仅要考虑数据类型的直接对应,还要注意特定数据类型在不同系统中的表现差异,确保数据的一致性和完整性。
28 4