s-s-rS 报告查看器 + ASP.NET 凭据 401 异常

Posted

技术标签:

【中文标题】s-s-rS 报告查看器 + ASP.NET 凭据 401 异常【英文标题】:s-s-rS Report Viewer + ASP.NET Credentials 401 Exception 【发布时间】:2010-11-29 04:22:37 【问题描述】:

我在 SQL2005 报告服务器上保存了一份报告,我想返回该报告的呈现 PDF。我在使用本地 *.rdlc 文件 (and I've blogged about it) 时已经发现了这一点,但在 *.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://mys-s-rsbox", 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:devport) 中运行时确实有效,在我的开发箱 (http://localhost/myApplication) 上运行时确实有效。在我们的测试或生产服务器上运行时,它不起作用。 我已经尝试过在 web.config 中使用和不使用 system.net.defaultProxy 设置的解决方案。两者都不起作用。

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

【问题讨论】:

模拟用户是否有权访问报表服务器——尤其是那个报表? 您是否尝试过在您的开发机器 (localhost) 上以模拟用户身份运行 IIS,以更接近地模拟您的测试服务器上发生的情况?这听起来像是您的模拟用户对报告服务器或报告服务器数据库的完全权限问题。我假设模拟用户是域帐户。 @NYSystemsAnalyst - 是的,模拟用户有权访问报表服务器上的相应目录。 【参考方案1】:

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

我们的解决方案是创建一个通用 domain\s-s-rs_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("s-s-rs_report_services", "password", "domain") ; 
        

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

【讨论】:

事实上,我认为在任何配置下都不会“允许”双跳。我不清楚为什么您的开发环境正常工作,但可能配置不同。 正如向我解释的那样,它适用于开发,因为它不算作从 localhost(作为客户端)-> localhost(作为 IIS)-> SRS 的一跳 仅供参考,管理员可以基于每个服务器配置委派。签出:serverfault.com/questions/16364/… 通过创建一个新的域用户,这是否意味着您将无法将报告限制在用户级别,因为使用您应用程序的每个人都将使用相同的凭据进行身份验证?谢谢【参考方案2】:

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

【讨论】:

不幸的是,我们开发人员受到环境的限制,在基础设施方面没有发言权。不过,感谢您给我一些新的阅读内容。

以上是关于s-s-rS 报告查看器 + ASP.NET 凭据 401 异常的主要内容,如果未能解决你的问题,请参考以下文章

s-s-rS 报表查看器无法将凭据从超链接传递到报表服务器

报表查看器无法访问其他数据库服务器中的报表

将凭据传递给 Sql Report Server 2008

如何使用 c# 在 asp.net 页面中部署或显示 s-s-rS 报告?

s-s-rS 报告未在 ASP.NET 网站中呈现

使用 s-s-rS 和 ASP.NET 合并以 Pdf 格式生成的报告