Solution for “WebException: The request failed with HTTP status 401: Unauthorized” Reporting Services error

by Dmitry [dimaka] Pavlov 12. October 2010 17:22

Problem:

I have faced with the problem yesterday. In the ASP.NET project I participate we use Microsoft SQL Server Reporting Services to display reports to the application user. We use ReportViewer control placed on the ASP.NET page. Our ASP.NET application and Reporting Services are hosted on 2 computers in the intranet. All is ok for local reports. But for remote reports we got the Reporting Services error:

“WebException: The request failed with HTTP status 401: Unauthorized”

Reason

After some research and googling I have found the explanation why the problem appeared. The reason for this error is that Report Server computer does not trust the computer where our APS.NET application is hosted. Well, it’s quite reasonable. So we decided to create a special Windows user with access to our Report Server. And we used this user credentials to get remote reports from ASP.NET application.

Solution

The way to use the special credentials for remote report requires to implement the IReportServerCredentials Interface. I am reposting here the code which is also available on MSDN link I have just mentioned:

[Serializable]
public sealed class MyReportServerCredentials : 
    IReportServerCredentials
{
    public WindowsIdentity ImpersonationUser
    {
        get
        {
            // Use the default Windows user.  Credentials will be
            // provided by the NetworkCredentials property.
            return null;
        }
    }

    public ICredentials NetworkCredentials
    {
        get
        {
            // Read the user information from the Web.config file.  
            // By reading the information on demand instead of 
            // storing it, the credentials will not be stored in 
            // session, reducing the vulnerable surface area to the
            // Web.config file, which can be secured with an ACL.

            // User name
            string userName = 
                ConfigurationManager.AppSettings
                    ["MyReportViewerUser"];

            if (string.IsNullOrEmpty(userName))
                throw new Exception(
                    "Missing user name from web.config file");

            // Password
            string password = 
                ConfigurationManager.AppSettings
                    ["MyReportViewerPassword"];

            if (string.IsNullOrEmpty(password))
                throw new Exception(
                    "Missing password from web.config file");

            // Domain
            string domain = 
                ConfigurationManager.AppSettings
                    ["MyReportViewerDomain"];

            if (string.IsNullOrEmpty(domain))
                throw new Exception(
                    "Missing domain from web.config file");

            return new NetworkCredential(userName, password, domain);
        }
    }

    public bool GetFormsCredentials(out Cookie authCookie, 
                out string userName, out string password, 
                out string authority)
    {
        authCookie = null;
        userName = null;
        password = null;
        authority = null;

        // Not using form credentials
        return false;
    }
}

After such class is implemented you could use it in following manner on your ASP.NET page:

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Init(object sender, EventArgs e)
    {
        ReportViewer1.ServerReport.ReportServerCredentials = 
            new MyReportServerCredentials();
    }
}

Hope that helps!

Tags:

.NET | ASP.NET | Coding | Microsoft | SQL Server | Tips | Tricks | Visual Studio | Reporting Services

Comments

Calendar

<<  May 2012  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar