7

我有一个保存在 SQL2005 报告服务器上的报告,我想返回此报告的呈现 PDF。我在使用本地 *.rdlc 文件时已经发现了这一点(并且我已经在博客上写过),但在 *.rdl 驻留在报告服务器上时却没有。我在线路上收到401 Not Authorized错误...

reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters);

这是用于呈现报告的方法。

public byte[] Render(IReportDefinition reportDefinition)
{
    var reportViewer = new ReportViewer();
    byte[] renderedReport;
    try
    {
        var credentials = new WindowsImpersonationCredentials();
        reportViewer.ServerReport.ReportServerUrl = new Uri("http://myssrsbox", UrlKind.Absolute);
        reportViewer.ServerReport.ReportServerCredentials = credentials;
        reportViewer.ServerReport.ReportPath = reportDefinition.Path;
        // Exception is thrown on the following line...
        reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters);

        string mimeType;
        string encoding;
        string filenameExtension;
        string[] streams;
        Warning[] warnings;

        renderedReport = reportViewer.ServerReport.Render(reportDefinition.OutputType, reportDefinition.DeviceInfo, out mimeType, out encoding, out filenameExtension, out streams, out warnings);
    }
    catch (Exception ex)
    {
        // log the error...
        throw;
    }
    finally
    {
        reportViewer.Dispose();
    }
    return renderedReport;
}

您缺少的另一件事是 WindowsImpersonationCredentials 类。

public class WindowsImpersonationCredentials : IReportServerCredentials
{
    public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority)
    {
        authCookie = null;
        userName = password = authority = null;
        return false;
    }

    public WindowsIdentity ImpersonationUser
    {
        get { return WindowsIdentity.GetCurrent(); }
    }

    public ICredentials NetworkCredentials
    {
        get { return null; }
    }

    public override string ToString()
    {
        return String.Format("WindowsIdentity: {0} ({1})", this.ImpersonationUser.Name, this.ImpersonationUser.User.Value);
    }
}

您可能需要了解的其他事项...

  • 这是在 Intranet 上运行的,并且模拟已打开。
  • 日志记录表明模拟用户设置正确。
  • 这在 Visual Studio ( ) 中运行时确实有效,并且我的开发框 ( )上运行时也有效。在我们的测试或生产服务器上运行时,它不起作用。http://localhost:devporthttp://localhost/myApplication
  • 我已经尝试过在 web.config 中使用和不使用 system.net.defaultProxy 设置的解决方案。都没有奏效。

我究竟做错了什么?是服务器设置吗?是代码吗?是 web.config 吗?

4

2 回答 2

6

我们终于找到了问题所在。我们的网络管理员已禁用双跳,因此当模拟正确连接为domain\jmeyer时,应用程序仍在尝试使用 连接到 SRS 框domain\web01$。为什么会这样设置?因为双跳是一个巨大的安全漏洞。(或者有人告诉我。这听起来像你会在The Daily WTF上读到的东西吗?)

我们的解决方案是创建一个通用domain\ssrs_report_services用户,并使用以下网络凭据与该用户连接

public class CustomCredentials : IReportServerCredentials
{
    public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority)
    {
        authCookie = null;
        userName = password = authority = null;
        return false;
    }

    public WindowsIdentity ImpersonationUser
    {
        get { return null; }
    }

    public ICredentials NetworkCredentials
    {
        get { return new NetworkCredential("ssrs_report_services", "password", "domain") ; }
    }    
}

以上是您可以在互联网上找到的经典示例解决方案。

于 2009-09-17T15:49:01.433 回答
2

允许“双跳” - 切换 Kerberos 身份验证......(只要它工作正常!)

于 2009-09-21T14:04:29.960 回答