在 C# 中使用 WebRequest 时为 Microsoft Report Server 提供凭据

发布于 2025-01-09 00:48:24 字数 1896 浏览 1 评论 0原文

我想使用我的 C# 代码从我们的 Microsoft Report Server 下载 PDF 报告。我不知道为什么,但我做错了什么。我总是收到身份验证失败的错误(HTTP 401)。

public static async Task<Stream> DownloadWebDocument(string url) {
    if (string.IsNullOrEmpty(url))
        throw new ArgumentNullException(nameof(url));

    WebRequest request = WebRequest.Create(url);

    request.Method = "GET";
    request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
    request.Credentials = new NetworkCredential("MyUsername", "MyPassword", "MyDomain");

    //request.Headers.Add("Authorization", $"Basic {Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("MyUsername:MyPassword"))}");

    try {
        using WebResponse response = await request.GetResponseAsync();

        return response.GetResponseStream();
    } catch (Exception ex) {
        var a = ex.Message;

        throw;
    }

    //return await DownloadWebDocument(uri);
}

这段代码总是会遇到异常。但为什么?

PS:

根据要求,这是堆栈跟踪。没有内在的例外。

   bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   bei System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   bei DE.ZA.TrailerLoadingAssistant.Web.Code.WebHelper.<DownloadWebDocument>d__0.MoveNext() in C:\Users\Reichelt\source\repos\DE.ZA.TrailerLoading\DE.ZA.TrailerLoadingAssistant.Web\Code\WebHelper.cs:Zeile 28.

I would like to download a PDF report from our Microsoft Report Server using my C# code. I don't know why, but I' m doing something wrong. I always get an error back that the authentication failed (HTTP 401).

public static async Task<Stream> DownloadWebDocument(string url) {
    if (string.IsNullOrEmpty(url))
        throw new ArgumentNullException(nameof(url));

    WebRequest request = WebRequest.Create(url);

    request.Method = "GET";
    request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
    request.Credentials = new NetworkCredential("MyUsername", "MyPassword", "MyDomain");

    //request.Headers.Add("Authorization", 
quot;Basic {Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("MyUsername:MyPassword"))}");

    try {
        using WebResponse response = await request.GetResponseAsync();

        return response.GetResponseStream();
    } catch (Exception ex) {
        var a = ex.Message;

        throw;
    }

    //return await DownloadWebDocument(uri);
}

This code always runs into the exception. But why?

PS:

As requested, here's the stack trace. There is no inner exception.

   bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   bei System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   bei DE.ZA.TrailerLoadingAssistant.Web.Code.WebHelper.<DownloadWebDocument>d__0.MoveNext() in C:\Users\Reichelt\source\repos\DE.ZA.TrailerLoading\DE.ZA.TrailerLoadingAssistant.Web\Code\WebHelper.cs:Zeile 28.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦旅人picnic 2025-01-16 00:48:25

实际上我使用不同的方法将我的报告呈现为 PDF 文档:

    public static byte[] DownloadAsPDF(string ReportServer, string ReportPath)
    {
        ReportViewer ReportViewer1 = new ReportViewer();
        ReportViewer1.ServerReport.ReportServerCredentials = new 
CustomReportCredentials("MyUsername", "MyPassword", "MyDomain");
        ReportViewer1.ProcessingMode = 
Microsoft.Reporting.WebForms.ProcessingMode.Remote;
        ReportViewer1.ServerReport.ReportServerUrl = new Uri(ReportServer);
        ReportViewer1.ServerReport.ReportPath = ReportPath;

       
        byte[] bytes = ReportViewer1.ServerReport.Render("PDF");

        return bytes;
    }

    public class CustomReportCredentials : 
    Microsoft.Reporting.WebForms.IReportServerCredentials
    {
        // local variable for network credential.    
        private string _UserName;
        private string _PassWord;
        private string _DomainName;
        public CustomReportCredentials(string UserName, string PassWord, 
string DomainName)
        {
            _UserName = UserName;
            _PassWord = PassWord;
            _DomainName = DomainName;
        }

        public System.Security.Principal.WindowsIdentity ImpersonationUser
        {
            get
            {
                return null;  // not use ImpersonationUser        
            }
        }

        public ICredentials NetworkCredentials
        {
            get
            {
                // use NetworkCredentials            
                return new NetworkCredential(_UserName, _PassWord, 
_DomainName);
            }
        }

        public bool GetFormsCredentials(out Cookie authCookie, out string 
user, out string password, out string authority)
        {
            authCookie = null;
            user = password = authority = null;
            return false;
        }
    }

Actually I use different method to render my report as PDF document:

    public static byte[] DownloadAsPDF(string ReportServer, string ReportPath)
    {
        ReportViewer ReportViewer1 = new ReportViewer();
        ReportViewer1.ServerReport.ReportServerCredentials = new 
CustomReportCredentials("MyUsername", "MyPassword", "MyDomain");
        ReportViewer1.ProcessingMode = 
Microsoft.Reporting.WebForms.ProcessingMode.Remote;
        ReportViewer1.ServerReport.ReportServerUrl = new Uri(ReportServer);
        ReportViewer1.ServerReport.ReportPath = ReportPath;

       
        byte[] bytes = ReportViewer1.ServerReport.Render("PDF");

        return bytes;
    }

    public class CustomReportCredentials : 
    Microsoft.Reporting.WebForms.IReportServerCredentials
    {
        // local variable for network credential.    
        private string _UserName;
        private string _PassWord;
        private string _DomainName;
        public CustomReportCredentials(string UserName, string PassWord, 
string DomainName)
        {
            _UserName = UserName;
            _PassWord = PassWord;
            _DomainName = DomainName;
        }

        public System.Security.Principal.WindowsIdentity ImpersonationUser
        {
            get
            {
                return null;  // not use ImpersonationUser        
            }
        }

        public ICredentials NetworkCredentials
        {
            get
            {
                // use NetworkCredentials            
                return new NetworkCredential(_UserName, _PassWord, 
_DomainName);
            }
        }

        public bool GetFormsCredentials(out Cookie authCookie, out string 
user, out string password, out string authority)
        {
            authCookie = null;
            user = password = authority = null;
            return false;
        }
    }
廻憶裏菂餘溫 2025-01-16 00:48:24

我意识到,如果我使用 request.Credentials = CredentialCache.DefaultCredentials,它就可以工作。所以我的凭证肯定有问题。但绝对没有错别字。

我遇到过这个问题,似乎有人正在更改网络权限。一周使用 Credentials 可以工作,然后下周使用 DefaultCredentials 就可以工作。真的很奇怪,所以我放入了 Try/Catch 并在服务帐户失败时诉诸 DefaultCredentials,请参阅代码注释:

public class SRSHelper
{
    private ReportingService2005 rsServ;
    private ReportingExecution2005 rsExec = new ReportingExecution2005();
    private ReportParameter[] reportParameters;
    private ExecutionInfo execInfo = null;

    public SRSHelper(string reportUserName, string decryptedPassword, string reportDomain, string reportServerURL)
     {
        rsServ = new ReportingService2005(reportServerURL);
        rsExec.Url = reportServerURL + @"ReportExecution2005.asmx";

        System.Net.NetworkCredential creds = new System.Net.NetworkCredential();
        creds.UserName = reportUserName;
        creds.Password = decryptedPassword;
        creds.Domain = reportDomain;
        rsExec.Credentials = creds;
        rsServ.Credentials = creds;
     }

    public ReportParameter[] GetSRSReportParameters(string reportName)
    {
        string report = "/Reporting/" + reportName;
        bool forRendering = false;
        string historyID = null;
        ParameterValue[] values = null;
        DataSourceCredentials[] credentials = null;

        try
        {
            return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
        }
        catch
        {
            //If the Service Account credentials fail to work - try the users credentials - XYZ vendor regularly change things around or the network fails or for some reason beyond our control we have to change the settings.
            rsExec.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            rsServ.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
        }
            
    }

I realized, that if I use request.Credentials = CredentialCache.DefaultCredentials, it works. So there must be something wrong with my credentials. But it's definitely no typo.

I've had this problem and it seemed someone was changing the network permissions. One week using Credentials would work then the next week using DefaultCredentials worked. Really strange, so I put in a Try/Catch and resort to the DefaultCredentials if the Service Account fails, see the code comment:

public class SRSHelper
{
    private ReportingService2005 rsServ;
    private ReportingExecution2005 rsExec = new ReportingExecution2005();
    private ReportParameter[] reportParameters;
    private ExecutionInfo execInfo = null;

    public SRSHelper(string reportUserName, string decryptedPassword, string reportDomain, string reportServerURL)
     {
        rsServ = new ReportingService2005(reportServerURL);
        rsExec.Url = reportServerURL + @"ReportExecution2005.asmx";

        System.Net.NetworkCredential creds = new System.Net.NetworkCredential();
        creds.UserName = reportUserName;
        creds.Password = decryptedPassword;
        creds.Domain = reportDomain;
        rsExec.Credentials = creds;
        rsServ.Credentials = creds;
     }

    public ReportParameter[] GetSRSReportParameters(string reportName)
    {
        string report = "/Reporting/" + reportName;
        bool forRendering = false;
        string historyID = null;
        ParameterValue[] values = null;
        DataSourceCredentials[] credentials = null;

        try
        {
            return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
        }
        catch
        {
            //If the Service Account credentials fail to work - try the users credentials - XYZ vendor regularly change things around or the network fails or for some reason beyond our control we have to change the settings.
            rsExec.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            rsServ.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
        }
            
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文