简体   繁体   English

SSRS报告查看器+ ASP.NET凭据401例外

[英]SSRS Report Viewer + ASP.NET Credentials 401 Exception

I have a report saved on a SQL2005 reporting server, and I want to return a rendered PDF of this report. 我有一个保存在SQL2005报告服务器上的报告,我想返回此报告的呈现PDF。 I've figured this out when working with a local *.rdlc file ( and I've blogged about it ), but not when the *.rdl resides on a reporting server. 我在使用本地* .rdlc文件时已经想到了这一点( 我已经在博客上发表过这篇文章 ),但是当* .rdl驻留在报表服务器上时却没有。 I am getting a 401 Not Authorized error at the line... 我在线上收到401 Not Notized错误...

reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters);

Here's the method used to render the report. 这是用于呈现报告的方法。

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;
}

The other thing that you're missing is the WindowsImpersonationCredentials class. 您缺少的另一件事是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);
    }
}

Other things you may need to know... 您可能需要了解的其他事项......

  • This is running on an intranet, and impersonation is turned on. 这是在Intranet上运行,并且模拟已打开。
  • Logging indicates that the impersonation user is being set correctly. 日志记录表示正在正确设置模拟用户。
  • This does work when running in Visual Studio ( http://localhost:devport ), and it does work when running on my development box ( http://localhost/myApplication ). (在Visual Studio中运行时,这确实工作 http://localhost:devport )在我的开发机器上运行(时,和它的工作 http://localhost/myApplication )。 It does not work when running on our test or production servers. 在我们的测试或生产服务器上运行时,它不起作用
  • I have tried solutions both with and without system.net.defaultProxy settings in web.config. 我在web.config中尝试过使用和不使用system.net.defaultProxy设置的解决方案。 Neither worked. 都没有奏效。

What am I doing wrong? 我究竟做错了什么? Is it a server setting? 它是服务器设置吗? Is it code? 是代码吗? Is it web.config? 是web.config吗?

We did finally figure out the problem. 我们终于弄明白了这个问题。 Our network administrators have disabled double-hopping, so while the impersonation was correctly connecting as domain\\jmeyer , the application was still attempting to connect to the SRS box with domain\\web01$ . 我们的网络管理员已禁用双跳,因此当模拟正确连接为domain\\jmeyer ,应用程序仍尝试使用domain\\web01$连接到SRS框。 Why is it set up like this? 为什么这样设置? Because double-hopping is a massive security hole. 因为双跳是一个巨大的安全漏洞。 (Or so I was told. Does this sound like something you would read on The Daily WTF ?) (或者有人告诉我。这听起来像是你会在每日WTF上看到吗?)

Our solution was to create a generic domain\\ssrs_report_services user, and connect with that user with the following network credentials 我们的解决方案是创建一个通用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") ; }
    }    
}

The above is the classic example solution that you can find all over the internets. 以上是您可以在整个互联网上找到的经典示例解决方案。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM