SSRS 报告查看器 + ASP.NET 凭据 401 异常
我在 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:devport
) 中运行时有效,在我的开发盒上运行时有效 (http://localhost/myApplication
)。在我们的测试或生产服务器上运行时它不起作用。 - 我尝试过在 web.config 中使用和不使用 system.net.defaultProxy 设置的解决方案。两者都不起作用。
我做错了什么?是服务器设置吗?是代码吗?是 web.config 吗?
I have a report saved on a SQL2005 reporting server, and I want to return a rendered PDF of this report. 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. I am getting a 401 Not Authorized error at the line...
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.
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.
- 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
). 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. Neither worked.
What am I doing wrong? Is it a server setting? Is it code? Is it web.config?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我们终于弄清楚了问题所在。我们的网络管理员已禁用双跳,因此虽然模拟已正确连接为
domain\jmeyer
,但应用程序仍在尝试使用domain\web01$
连接到 SRS 框>。为什么要这样设置呢?因为双跳是一个巨大的安全漏洞。 (至少有人告诉我。这听起来像您在 The Daily WTF 上读到的东西吗?)我们的解决方案是创建通用
domain\ssrs_report_services
用户,并使用以下网络凭据与该用户连接以上是您可以在 Internet 上找到的经典示例解决方案。
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 withdomain\web01$
. 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?)Our solution was to create a generic
domain\ssrs_report_services
user, and connect with that user with the following network credentialsThe above is the classic example solution that you can find all over the internets.
允许“双跳” - 切换 Kerberos 身份验证...(只要它正常工作!)
"Double hopping" is allowed - swith on Kerberos authentication ... (so long as it is working properly!)