在SSRS 2008实现匿名访问报表

日期: 2010-01-10 作者:lonely7345 来源:TechTarget中国 英文

    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 Cookies {get;}
  IEnumerable Headers {get;}
  }
  public interface IReportServerConnection : IReportServerCredentials
  {
  Uri ReportServerUrl { get; }
  int Timeout { get; }
  }
  public interface class IReportServerConnection2 : IReportServerConnection, IReportServerCredentials
  {
  IEnumerable Cookies {get;}
  IEnumerable Headers {get;}
  }

  从这两个接口的代码可以看出,他们的实例可以当做IReportServerCredentials来使用,所以上面介绍的方法对于他们们的实现同样管用。他们的属性值同样默认存储在SessionState中,当SessionState禁止时,我们要提供其它的访问方式,以下是我们的实现:

  view plaincopy to clipboardprint
  [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 Cookies
  {
  get { return null; }
  }
  public IEnumerable 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 Cookies
  {
  get { return null; }
  }
  public IEnumerable 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配置:

  view plaincopy to clipboardprint

  同样的,我们直接赋值给ReportView的属性,就可以实现报表的“匿名访问”。

  view plaincopy to clipboardprint

  this.ReportViewer1.ServerReport.ReportServerCredentials = new MyReportServerConnection();

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐