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!