将身份验证标头传递给iframe中的图像请求

时间:2013-04-25 10:53:28

标签: asp.net ssrs-2008 reporting-services windows-authentication basic-authentication

我确信我的问题标题没有多大意义,但我现在想不出来。

问题:我的主要任务是在ASP.NET MVC应用程序的一个页面内的弹出窗口中显示SSRS报告的所有页面

为实现这一点,我采用了以下方法:

  1. 在MyPage.cshtml中添加一个jQuery弹出窗口(我需要在此弹出窗口中显示报告内容)
  2. 当此弹出窗口打开时(在某些客户端操作上),我向第二页proxyPage.aspx发出jquery ajax请求
  3. 在代理页面上,我使用网络凭据向reportserver发送webrequest并获取报告html

        WebRequest request = WebRequest.Create( "http://MyReportServer/ReportServer?/ MyReportName&rs:Command=Render&rs:Format =HTML4.0&rc:Toolbar=false&Param1=blabla123");
        request.Credentials = new NetworkCredential(MYUSERNAME, MYPASSWORD);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        Stream receiveStream = response.GetResponseStream();
        StreamReader readStream = new StreamReader(receiveStream, System.Text.Encoding.UTF8);
        string str = readStream.ReadToEnd();
        Response.Write(str);
    
  4. 来自proxyPage的HTML我在popup中写入div或使用iframe在其中显示完整的代理页面。

  5. 直到这里事情进展顺利,此后我又遇到了另一个问题,我正在写这个问题

  6. 当报表的HTML在弹出窗口中呈现时,它会向报表服务器请求检索嵌入在报表中的图像。

  7. 由于这些报表服务器请求不像我在步骤3中那样发送网络凭据,因此我收到输入凭据的提示。

    我需要一种方法,通过这种方法,这些图像请求可能会以某种方式通过我之前提供的凭据进行身份验证。

1 个答案:

答案 0 :(得分:0)

SSRS将在您指定的位置流式传输资源。

private byte[] InternalRenderReport(Report report, List<ReportParameter> parameters, string format, int pageNumber, ref int totalPages, string virtualTempFolder, string physicalTempFolder)
        {
            CheckConnection();
            byte[] result = null;
            ReportExecution2005.ReportExecutionService _execService=new ReportExecution2005.ReportExecutionService();


            sys = _systemService.GetCurrentSystem();
            _execService.Url = sys.ReportingServices.ServiceRootURL+"/ReportExecution2005.asmx";
            NetworkCredential credentials = new NetworkCredential(sys.ReportingServices.Credentials.UserName, 
                                                                 sys.ReportingServices.Credentials.Password,
                                                                 sys.ReportingServices.Credentials.Domain);
            _execService.Credentials=credentials;

            ReportExecution2005.ParameterValue[] rsParams = null;
            if (parameters != null)
            {
                rsParams = new ReportExecution2005.ParameterValue[parameters.Count];
                int x = 0;
                foreach (ReportParameter p in parameters)
                {
                    rsParams[x] = new ReportExecution2005.ParameterValue();
                    rsParams[x].Name = p.ParameterName;
                    rsParams[x].Value = p.SelectedValue;
                    x++;
                }
            }
            StringBuilder devInfo = new StringBuilder();
            if (format.ToUpper().StartsWith("HTML"))
            {
                devInfo.Append("<DeviceInfo>");
                devInfo.Append("<HTMLFragment>True</HTMLFragment>");
                devInfo.Append("<Section>" + pageNumber.ToString() +"</Section>");
                devInfo.Append("<StreamRoot>" + virtualTempFolder + "</StreamRoot>");
                /*devInfo.Append("<Zoom>200</Zoom>");*/
                devInfo.Append("</DeviceInfo>");                
            }
            else
                 devInfo.Append("<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>");

            string extension;
            string mimeType;
            string encoding;
            string[] streamIDs = null;
            ReportExecution2005.Warning[] warnings = null;




            ReportExecution2005.ExecutionHeader execHeader = new ReportExecution2005.ExecutionHeader();
            ReportExecution2005.ExecutionInfo rpt = _execService.LoadReport(report.ReportPath, null);

            if(rsParams!=null)
                _execService.SetExecutionParameters(rsParams, "en-us");
            _execService.ExecutionHeaderValue = execHeader;
            _execService.ExecutionHeaderValue.ExecutionID = rpt.ExecutionID;


            //result = _execService.Render2(format, devInfo, ReportExecution2005.PageCountMode.Actual, out extension, out mimeType, out encoding, out warnings, streamIDs);
            result =  _execService.Render(format, devInfo.ToString(), out extension, out mimeType, out encoding, out warnings, out streamIDs);

            if (format.ToUpper().StartsWith("HTML"))
            {


                // For each image stream returned by the call to render,
                // render the stream and save it to the application root
                string FilePath = physicalTempFolder;
                byte[] image;
                // For each image stream returned by the call to render,
                // render the stream and save it to the application root
                foreach (string streamID in streamIDs)
                {
                    image = _execService.RenderStream("HTML4.0", streamID, null, out encoding, out mimeType);

                    FileStream stream = File.OpenWrite(FilePath + streamID);
                    stream.Write(image, 0, image.Length);                    
                    stream.Close();
                }
            }

            rpt = _execService.GetExecutionInfo();
            totalPages = rpt.NumPages;

            return result;
        }

这将返回原始HTML或推送文件的内容。我将Temp文件夹添加到要部署到服务器的解决方案中。你可以将一个web.config文件放在temp文件夹中,其中包含以下内容,以便在使用流时ssrs将呈现扩展内容:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <staticContent>

      <mimeMap fileExtension=".*" mimeType="image/png" />


    </staticContent>
    <handlers>
      <clear />

      <add name="StaticFile" path="*" verb="*" type="" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" scriptProcessor="" resourceType="Either" requireAccess="Read" allowPathInfo="false" preCondition="" responseBufferLimit="4194304" />
    </handlers>
  </system.webServer>
</configuration>

然后使用以下函数来获取物理和Virtual Temp文件夹:

PhyscicalTempFolder= AppDomain.CurrentDomain.BaseDirectory + @"Temp\";
VirtualTempFolder=return  Url.Content("~/Temp/");

最后在每天清理后你可以添加类似于:

的powershell命令
Remove-Item D:\xxx\WebApplications\ExternalReports\Temp\* -exclude *.config

然后添加一个调用PS脚本的.bat:

powershell -command "& 'C:\xxx\Scripts\SSRSCleanTempFiles\SSRSCleanTempFiles.ps1'"

使用此功能,您可以在服务器上配置计划任务,以便每天调用.bat文件并清理应用程序的临时文件夹。