【问题标题】:SSRS server gives a 401 Unauthorised response, but only when called via the APIsSSRS 服务器给出 401 Unauthorized 响应,但仅在通过 API 调用时
【发布时间】:2021-04-20 12:13:33
【问题描述】:

我正在尝试从我的应用程序中的服务器运行 SSRS 报告,并将结果下载为 PDF。为此,我为服务器上有权运行报告的用户提供网络凭据。

这一切都适用于我的本地开发人员 SSRS 副本,我可以运行报告并愉快地继续保存它。但是,当我在服务器上运行 SSRS 并将应用程序指向该服务器时,我会在尝试运行报告时立即收到 401 Unauthorized 错误。

我可以通过我尝试运行应用程序的同一台计算机上的浏览器访问同一远程服务器,使用应用程序中失败的相同凭据,并成功运行相关报告。网上已有的解决方案似乎都没有适用/帮助。

下面是我用来尝试执行报告的代码 - ReportingUsername、ReportingPassword 被设置为在浏览器中工作的凭据,ReportingDomain 被设置为使用本地帐户的 PC 的名称(这是一个故障排除步骤,我以前没有它也不起作用),设置 PreAuthenticate 是另一个故障排除步骤。 ReportServerUrl 为 http://server/ReportServer(服务器在 80 端口上作为默认实例运行),JCReportFolder 设置为服务器上报告所在的文件夹。

ReportKey 只是用来运行报表的参数。


//setup credentials and URL of report execution service
ReportExecutionService rs = new ReportExecutionService();
NetworkCredential nwk = new System.Net.NetworkCredential(ReportingUsername, ReportingPassword, ReportingDomain);
rs.Credentials = nwk;
rs.PreAuthenticate = true;
rs.Url = ReportServerUrl + "/" + "reportexecution2005.asmx";
rs.ExecutionHeaderValue = new ExecutionHeader();
var executionInfo = new ExecutionInfo();
executionInfo = rs.LoadReport("/" + JCReportFolder + "/" + reportName, null);

//set report key
List<ParameterValue> parameters = new List<ParameterValue>();
parameters.Add(new ParameterValue { Name = "ReportKey", Value = reportKey });
rs.SetExecutionParameters(parameters.ToArray(), "en-US");


string deviceInfo = "<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
string mimeType;
string encoding;
string[] streamId;
Warning[] warning;

var result = rs.Render("PDF", deviceInfo, out mimeType, out encoding, out encoding, out warning, out streamId);

有人有什么建议吗?到目前为止尝试过:

  • 确认服务器未使用 Kerberos 身份验证,设置为 NTLM
  • 使用中的已检查帐户具有报告的完全权限,并且可以在 Web 浏览器中访问报告(从通过 C# 代码运行时获取 401 的同一台计算机),甚至尝试将其临时设为管理员以查看是否会帮助
  • 数据库连接使用报表服务器上存储的凭据,而不是提供的凭据,因此不是问题
  • 机器可以通过防火墙完全访问,并且可以看到 SSRS 机器

【问题讨论】:

  • 使用 SQL Server Management Studio 连接到远程数据库来调试问题。我相信您应该在连接字符串中使用默认凭据(请参阅:docs.microsoft.com/en-us/dotnet/api/…)Is Integrated Security=true;在 SSMS 的登录窗口上,它是 Windows 凭据。您需要从删除机器访问数据库才能执行报告。
  • 感谢@jdweng 的回复,但是我特别希望使用与用户当前运行的不同的 Windows 凭据 - 在我看来,默认凭据只会使其身份验证为当前用户绝对无权访问
  • 您必须小心不要让黑客访问服务器。许多网络不允许使用用户名、密码作为凭据,以防止黑客侵入网络。它们只允许来自网络内部的安全连接,并且很少允许来自防火墙外部的访问。查看角色:docs.microsoft.com/en-us/aspnet/web-forms/overview/…
  • 您的本地和目标 SQL Server 的版本是什么?对http://server/ReportServer/reportexecution2005.asmx?wsdl 的请求是否成功?
  • 哪个调用失败了?第一个LoadReport?

标签: c# reporting-services


【解决方案1】:

因此,经过一番摸索,这被证明是一个完全荒谬的问题。

事实证明,由于某种原因设置 ReportExecutionService.Url 会清除 ReportExecutionService.Credentials。简单地移动线

rs.Credentials = nwk;

到之前

executionInfo = rs.LoadReport("/" + JCReportFolder + "/" + reportName, null);

彻底解决了问题。

我的猜测是我在本地没有遇到此问题,因为该应用程序实际上默认以我的本地管理员帐户执行,因此掩盖了该问题。

【讨论】:

    【解决方案2】:

    确保 .net 使用受支持的 TLS 版本,当 MS 增加 windows 服务器使用的默认 TLS 版本时,我们遇到了看似随机的身份验证问题。

    System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

    【讨论】:

    • 感谢@Joral 不幸的是我还没有到设置证书和运行 TLS 的阶段,我现在只是通过端口 80 进行调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 2020-06-11
    相关资源
    最近更新 更多